[BACK]Return to rtld.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / libexec / ld.elf_so

Annotation of src/libexec/ld.elf_so/rtld.c, Revision 1.190.2.4

1.190.2.4! pgoyette    1: /*     $NetBSD: rtld.c,v 1.190.2.3 2018/10/20 06:58:22 pgoyette Exp $   */
1.1       cgd         2:
                      3: /*
                      4:  * Copyright 1996 John D. Polstra.
                      5:  * Copyright 1996 Matt Thomas <matt@3am-software.com>
1.87      mycroft     6:  * Copyright 2002 Charles M. Hannum <root@ihack.net>
1.1       cgd         7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by John Polstra.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34:
                     35: /*
                     36:  * Dynamic linker for ELF.
                     37:  *
                     38:  * John Polstra <jdp@polstra.com>.
                     39:  */
                     40:
1.107     skrll      41: #include <sys/cdefs.h>
                     42: #ifndef lint
1.190.2.4! pgoyette   43: __RCSID("$NetBSD: rtld.c,v 1.190.2.3 2018/10/20 06:58:22 pgoyette Exp $");
1.107     skrll      44: #endif /* not lint */
                     45:
1.141     joerg      46: #include <sys/param.h>
                     47: #include <sys/atomic.h>
                     48: #include <sys/mman.h>
1.1       cgd        49: #include <err.h>
                     50: #include <errno.h>
                     51: #include <fcntl.h>
1.141     joerg      52: #include <lwp.h>
1.1       cgd        53: #include <stdarg.h>
                     54: #include <stdio.h>
                     55: #include <stdlib.h>
                     56: #include <string.h>
                     57: #include <unistd.h>
                     58: #include <dirent.h>
                     59:
                     60: #include <ctype.h>
                     61:
1.2       cgd        62: #include <dlfcn.h>
1.1       cgd        63: #include "debug.h"
                     64: #include "rtld.h"
1.3       cgd        65:
1.20      kleink     66: #if !defined(lint)
1.3       cgd        67: #include "sysident.h"
1.20      kleink     68: #endif
1.1       cgd        69:
                     70: /*
                     71:  * Function declarations.
                     72:  */
1.113     christos   73: static void     _rtld_init(caddr_t, caddr_t, const char *);
1.98      skrll      74: static void     _rtld_exit(void);
1.15      christos   75:
1.98      skrll      76: Elf_Addr        _rtld(Elf_Addr *, Elf_Addr);
1.15      christos   77:
1.1       cgd        78:
                     79: /*
                     80:  * Data declarations.
                     81:  */
1.15      christos   82: static char    *error_message; /* Message for dlopen(), or NULL */
1.1       cgd        83:
1.15      christos   84: struct r_debug  _rtld_debug;   /* for GDB; */
                     85: bool            _rtld_trust;   /* False for setuid and setgid programs */
                     86: Obj_Entry      *_rtld_objlist; /* Head of linked list of shared objects */
                     87: Obj_Entry     **_rtld_objtail; /* Link field of last object in list */
                     88: Obj_Entry      *_rtld_objmain; /* The main program shared object */
                     89: Obj_Entry       _rtld_objself; /* The dynamic linker shared object */
1.131     skrll      90: u_int          _rtld_objcount; /* Number of objects in _rtld_objlist */
                     91: u_int          _rtld_objloads; /* Number of objects loaded in _rtld_objlist */
1.147     joerg      92: u_int          _rtld_objgen;   /* Generation count for _rtld_objlist */
1.120     matt       93: const char     _rtld_path[] = _PATH_RTLD;
                     94:
                     95: /* Initialize a fake symbol for resolving undefined weak references. */
                     96: Elf_Sym                _rtld_sym_zero = {
                     97:     .st_info   = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
                     98:     .st_shndx  = SHN_ABS,
                     99: };
1.126     skrll     100: size_t _rtld_pagesz;   /* Page size, as provided by kernel */
1.25      mycroft   101:
1.22      kleink    102: Search_Path    *_rtld_default_paths;
1.15      christos  103: Search_Path    *_rtld_paths;
1.28      christos  104:
                    105: Library_Xform  *_rtld_xforms;
1.156     joerg     106: static void    *auxinfo;
1.28      christos  107:
1.1       cgd       108: /*
                    109:  * Global declarations normally provided by crt0.
                    110:  */
1.15      christos  111: char           *__progname;
                    112: char          **environ;
1.1       cgd       113:
1.141     joerg     114: static volatile bool _rtld_mutex_may_recurse;
                    115:
1.108     uwe       116: #if defined(RTLD_DEBUG)
1.112     scw       117: #ifndef __sh__
1.9       tv        118: extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
1.108     uwe       119: #else  /* 32-bit SuperH */
                    120: register Elf_Addr *_GLOBAL_OFFSET_TABLE_ asm("r12");
                    121: #endif
                    122: #endif /* RTLD_DEBUG */
1.15      christos  123: extern Elf_Dyn  _DYNAMIC;
1.8       tv        124:
1.148     joerg     125: static void _rtld_call_fini_functions(sigset_t *, int);
                    126: static void _rtld_call_init_functions(sigset_t *);
1.117     ad        127: static void _rtld_initlist_visit(Objlist *, Obj_Entry *, int);
                    128: static void _rtld_initlist_tsort(Objlist *, int);
1.98      skrll     129: static Obj_Entry *_rtld_dlcheck(void *);
                    130: static void _rtld_init_dag(Obj_Entry *);
                    131: static void _rtld_init_dag1(Obj_Entry *, Obj_Entry *);
                    132: static void _rtld_objlist_remove(Objlist *, Obj_Entry *);
1.117     ad        133: static void _rtld_objlist_clear(Objlist *);
1.148     joerg     134: static void _rtld_unload_object(sigset_t *, Obj_Entry *, bool);
1.98      skrll     135: static void _rtld_unref_dag(Obj_Entry *);
                    136: static Obj_Entry *_rtld_obj_from_addr(const void *);
1.15      christos  137:
1.158     matt      138: static inline void
1.174     joerg     139: _rtld_call_initfini_function(const Obj_Entry *obj, Elf_Addr func, sigset_t *mask)
1.158     matt      140: {
                    141:        _rtld_exclusive_exit(mask);
1.174     joerg     142:        _rtld_call_function_void(obj, func);
1.158     matt      143:        _rtld_exclusive_enter(mask);
                    144: }
                    145:
                    146: static void
                    147: _rtld_call_fini_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
                    148: {
1.174     joerg     149:        if (obj->fini_arraysz == 0 && (obj->fini == 0 || obj->fini_called))
                    150:                return;
                    151:
                    152:        if (obj->fini != 0 && !obj->fini_called) {
1.158     matt      153:                dbg (("calling fini function %s at %p%s", obj->path,
                    154:                    (void *)obj->fini,
                    155:                    obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
1.165     skrll     156:                obj->fini_called = 1;
1.174     joerg     157:                _rtld_call_initfini_function(obj, obj->fini, mask);
1.158     matt      158:        }
                    159: #ifdef HAVE_INITFINI_ARRAY
                    160:        /*
                    161:         * Now process the fini_array if it exists.  Simply go from
                    162:         * start to end.  We need to make restartable so just advance
                    163:         * the array pointer and decrement the size each time through
                    164:         * the loop.
                    165:         */
                    166:        while (obj->fini_arraysz > 0 && _rtld_objgen == cur_objgen) {
1.174     joerg     167:                Elf_Addr fini = *obj->fini_array++;
1.158     matt      168:                obj->fini_arraysz--;
                    169:                dbg (("calling fini array function %s at %p%s", obj->path,
                    170:                    (void *)fini,
                    171:                    obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
1.174     joerg     172:                _rtld_call_initfini_function(obj, fini, mask);
1.158     matt      173:        }
                    174: #endif /* HAVE_INITFINI_ARRAY */
                    175: }
                    176:
1.1       cgd       177: static void
1.148     joerg     178: _rtld_call_fini_functions(sigset_t *mask, int force)
1.1       cgd       179: {
1.117     ad        180:        Objlist_Entry *elm;
                    181:        Objlist finilist;
1.147     joerg     182:        u_int cur_objgen;
1.1       cgd       183:
1.117     ad        184:        dbg(("_rtld_call_fini_functions(%d)", force));
                    185:
1.147     joerg     186: restart:
                    187:        cur_objgen = ++_rtld_objgen;
1.117     ad        188:        SIMPLEQ_INIT(&finilist);
                    189:        _rtld_initlist_tsort(&finilist, 1);
                    190:
                    191:        /* First pass: objects _not_ marked with DF_1_INITFIRST. */
                    192:        SIMPLEQ_FOREACH(elm, &finilist, link) {
1.158     matt      193:                Obj_Entry * const obj = elm->obj;
                    194:                if (!obj->z_initfirst) {
                    195:                        if (obj->refcount > 0 && !force) {
                    196:                                continue;
                    197:                        }
                    198:                        /*
                    199:                         * XXX This can race against a concurrent dlclose().
                    200:                         * XXX In that case, the object could be unmapped before
                    201:                         * XXX the fini() call or the fini_array has completed.
                    202:                         */
                    203:                        _rtld_call_fini_function(obj, mask, cur_objgen);
                    204:                        if (_rtld_objgen != cur_objgen) {
                    205:                                dbg(("restarting fini iteration"));
                    206:                                _rtld_objlist_clear(&finilist);
                    207:                                goto restart;
1.117     ad        208:                }
1.147     joerg     209:                }
1.117     ad        210:        }
                    211:
                    212:        /* Second pass: objects marked with DF_1_INITFIRST. */
                    213:        SIMPLEQ_FOREACH(elm, &finilist, link) {
1.158     matt      214:                Obj_Entry * const obj = elm->obj;
1.117     ad        215:                if (obj->refcount > 0 && !force) {
                    216:                        continue;
                    217:                }
1.147     joerg     218:                /* XXX See above for the race condition here */
1.158     matt      219:                _rtld_call_fini_function(obj, mask, cur_objgen);
1.147     joerg     220:                if (_rtld_objgen != cur_objgen) {
                    221:                        dbg(("restarting fini iteration"));
                    222:                        _rtld_objlist_clear(&finilist);
                    223:                        goto restart;
                    224:                }
1.117     ad        225:        }
                    226:
                    227:         _rtld_objlist_clear(&finilist);
1.1       cgd       228: }
                    229:
                    230: static void
1.158     matt      231: _rtld_call_init_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
                    232: {
1.174     joerg     233:        if (obj->init_arraysz == 0 && (obj->init_called || obj->init == 0))
1.158     matt      234:                return;
1.174     joerg     235:
                    236:        if (!obj->init_called && obj->init != 0) {
1.158     matt      237:                dbg (("calling init function %s at %p%s",
                    238:                    obj->path, (void *)obj->init,
                    239:                    obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
                    240:                obj->init_called = 1;
1.174     joerg     241:                _rtld_call_initfini_function(obj, obj->init, mask);
1.158     matt      242:        }
                    243:
                    244: #ifdef HAVE_INITFINI_ARRAY
                    245:        /*
                    246:         * Now process the init_array if it exists.  Simply go from
                    247:         * start to end.  We need to make restartable so just advance
                    248:         * the array pointer and decrement the size each time through
                    249:         * the loop.
                    250:         */
                    251:        while (obj->init_arraysz > 0 && _rtld_objgen == cur_objgen) {
1.174     joerg     252:                Elf_Addr init = *obj->init_array++;
1.158     matt      253:                obj->init_arraysz--;
                    254:                dbg (("calling init_array function %s at %p%s",
                    255:                    obj->path, (void *)init,
                    256:                    obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
1.174     joerg     257:                _rtld_call_initfini_function(obj, init, mask);
1.158     matt      258:        }
                    259: #endif /* HAVE_INITFINI_ARRAY */
                    260: }
                    261:
1.188     joerg     262: static bool
                    263: _rtld_call_ifunc_functions(sigset_t *mask, Obj_Entry *obj, u_int cur_objgen)
                    264: {
                    265:        if (obj->ifunc_remaining
1.190.2.2  pgoyette  266: #if defined(IFUNC_NONPLT)
1.188     joerg     267:            || obj->ifunc_remaining_nonplt
                    268: #endif
                    269:        ) {
                    270:                _rtld_call_ifunc(obj, mask, cur_objgen);
                    271:                if (_rtld_objgen != cur_objgen) {
                    272:                        return true;
                    273:                }
                    274:        }
                    275:        return false;
                    276: }
                    277:
1.158     matt      278: static void
1.148     joerg     279: _rtld_call_init_functions(sigset_t *mask)
1.1       cgd       280: {
1.117     ad        281:        Objlist_Entry *elm;
                    282:        Objlist initlist;
1.147     joerg     283:        u_int cur_objgen;
1.94      simonb    284:
1.117     ad        285:        dbg(("_rtld_call_init_functions()"));
1.147     joerg     286:
                    287: restart:
                    288:        cur_objgen = ++_rtld_objgen;
1.117     ad        289:        SIMPLEQ_INIT(&initlist);
                    290:        _rtld_initlist_tsort(&initlist, 0);
                    291:
1.186     joerg     292:        /* First pass: objects with IRELATIVE relocations. */
                    293:        SIMPLEQ_FOREACH(elm, &initlist, link) {
1.188     joerg     294:                if (_rtld_call_ifunc_functions(mask, elm->obj, cur_objgen)) {
                    295:                        dbg(("restarting init iteration"));
                    296:                        _rtld_objlist_clear(&initlist);
                    297:                        goto restart;
1.186     joerg     298:                }
                    299:        }
1.188     joerg     300:        /*
                    301:         * XXX: For historic reasons, init/fini of the main object are called
                    302:         * from crt0. Don't introduce that mistake for ifunc, so look at
                    303:         * the head of _rtld_objlist that _rtld_initlist_tsort skipped.
                    304:         */
                    305:        if (_rtld_call_ifunc_functions(mask, _rtld_objlist, cur_objgen)) {
                    306:                dbg(("restarting init iteration"));
                    307:                _rtld_objlist_clear(&initlist);
                    308:                goto restart;
                    309:        }
1.186     joerg     310:
                    311:        /* Second pass: objects marked with DF_1_INITFIRST. */
1.117     ad        312:        SIMPLEQ_FOREACH(elm, &initlist, link) {
1.158     matt      313:                Obj_Entry * const obj = elm->obj;
                    314:                if (obj->z_initfirst) {
                    315:                        _rtld_call_init_function(obj, mask, cur_objgen);
                    316:                        if (_rtld_objgen != cur_objgen) {
                    317:                                dbg(("restarting init iteration"));
                    318:                                _rtld_objlist_clear(&initlist);
                    319:                                goto restart;
                    320:                        }
1.147     joerg     321:                }
1.117     ad        322:        }
                    323:
1.186     joerg     324:        /* Third pass: all other objects. */
1.117     ad        325:        SIMPLEQ_FOREACH(elm, &initlist, link) {
1.158     matt      326:                _rtld_call_init_function(elm->obj, mask, cur_objgen);
1.147     joerg     327:                if (_rtld_objgen != cur_objgen) {
                    328:                        dbg(("restarting init iteration"));
                    329:                        _rtld_objlist_clear(&initlist);
                    330:                        goto restart;
                    331:                }
1.14      pk        332:        }
1.117     ad        333:
                    334:         _rtld_objlist_clear(&initlist);
1.1       cgd       335: }
1.14      pk        336:
1.1       cgd       337: /*
                    338:  * Initialize the dynamic linker.  The argument is the address at which
                    339:  * the dynamic linker has been mapped into memory.  The primary task of
1.105     skrll     340:  * this function is to create an Obj_Entry for the dynamic linker and
                    341:  * to resolve the PLT relocation for platforms that need it (those that
                    342:  * define __HAVE_FUNCTION_DESCRIPTORS
1.1       cgd       343:  */
                    344: static void
1.114     christos  345: _rtld_init(caddr_t mapbase, caddr_t relocbase, const char *execname)
1.1       cgd       346: {
1.94      simonb    347:
1.14      pk        348:        /* Conjure up an Obj_Entry structure for the dynamic linker. */
1.120     matt      349:        _rtld_objself.path = __UNCONST(_rtld_path);
                    350:        _rtld_objself.pathlen = sizeof(_rtld_path)-1;
1.80      mycroft   351:        _rtld_objself.rtld = true;
                    352:        _rtld_objself.mapbase = mapbase;
                    353:        _rtld_objself.relocbase = relocbase;
                    354:        _rtld_objself.dynamic = (Elf_Dyn *) &_DYNAMIC;
1.119     christos  355:        _rtld_objself.strtab = "_rtld_sym_zero";
1.1       cgd       356:
1.120     matt      357:        /*
1.128     skrll     358:         * Set value to -relocbase so that
                    359:         *
                    360:         *     _rtld_objself.relocbase + _rtld_sym_zero.st_value == 0
                    361:         *
1.120     matt      362:         * This allows unresolved references to weak symbols to be computed
1.128     skrll     363:         * to a value of 0.
1.120     matt      364:         */
                    365:        _rtld_sym_zero.st_value = -(uintptr_t)relocbase;
                    366:
1.113     christos  367:        _rtld_digest_dynamic(_rtld_path, &_rtld_objself);
1.104     skrll     368:        assert(!_rtld_objself.needed);
1.105     skrll     369: #if !defined(__hppa__)
1.103     skrll     370:        assert(!_rtld_objself.pltrel && !_rtld_objself.pltrela);
1.105     skrll     371: #else
                    372:        _rtld_relocate_plt_objects(&_rtld_objself);
                    373: #endif
                    374: #if !defined(__mips__) && !defined(__hppa__)
1.104     skrll     375:        assert(!_rtld_objself.pltgot);
1.103     skrll     376: #endif
1.97      skrll     377: #if !defined(__arm__) && !defined(__mips__) && !defined(__sh__)
                    378:        /* ARM, MIPS and SH{3,5} have a bogus DT_TEXTREL. */
1.103     skrll     379:        assert(!_rtld_objself.textrel);
1.80      mycroft   380: #endif
1.13      christos  381:
1.114     christos  382:        _rtld_add_paths(execname, &_rtld_default_paths,
                    383:            RTLD_DEFAULT_LIBRARY_PATH);
1.13      christos  384:
1.123     mrg       385: #ifdef RTLD_ARCH_SUBDIR
                    386:        _rtld_add_paths(execname, &_rtld_default_paths,
                    387:            RTLD_DEFAULT_LIBRARY_PATH "/" RTLD_ARCH_SUBDIR);
                    388: #endif
                    389:
1.169     skrll     390:        /* Make the object list empty. */
1.14      pk        391:        _rtld_objlist = NULL;
                    392:        _rtld_objtail = &_rtld_objlist;
1.129     roy       393:        _rtld_objcount = 0;
1.1       cgd       394:
1.14      pk        395:        _rtld_debug.r_brk = _rtld_debug_state;
                    396:        _rtld_debug.r_state = RT_CONSISTENT;
1.1       cgd       397: }
1.14      pk        398:
1.1       cgd       399: /*
                    400:  * Cleanup procedure.  It will be called (by the atexit() mechanism) just
                    401:  * before the process exits.
                    402:  */
                    403: static void
1.98      skrll     404: _rtld_exit(void)
1.1       cgd       405: {
1.148     joerg     406:        sigset_t mask;
                    407:
1.15      christos  408:        dbg(("rtld_exit()"));
1.1       cgd       409:
1.148     joerg     410:        _rtld_exclusive_enter(&mask);
1.145     joerg     411:
1.148     joerg     412:        _rtld_call_fini_functions(&mask, 1);
1.145     joerg     413:
1.148     joerg     414:        _rtld_exclusive_exit(&mask);
1.1       cgd       415: }
1.14      pk        416:
1.156     joerg     417: __dso_public void *
                    418: _dlauxinfo(void)
                    419: {
                    420:        return auxinfo;
                    421: }
                    422:
1.1       cgd       423: /*
                    424:  * Main entry point for dynamic linking.  The argument is the stack
                    425:  * pointer.  The stack is expected to be laid out as described in the
                    426:  * SVR4 ABI specification, Intel 386 Processor Supplement.  Specifically,
                    427:  * the stack pointer points to a word containing ARGC.  Following that
                    428:  * in the stack is a null-terminated sequence of pointers to argument
                    429:  * strings.  Then comes a null-terminated sequence of pointers to
                    430:  * environment strings.  Finally, there is a sequence of "auxiliary
                    431:  * vector" entries.
                    432:  *
1.17      kleink    433:  * This function returns the entry point for the main program, the dynamic
                    434:  * linker's exit procedure in sp[0], and a pointer to the main object in
                    435:  * sp[1].
1.1       cgd       436:  */
                    437: Elf_Addr
1.98      skrll     438: _rtld(Elf_Addr *sp, Elf_Addr relocbase)
1.1       cgd       439: {
1.15      christos  440:        const AuxInfo  *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr,
1.53      christos  441:                       *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid,
                    442:                       *pAUX_ruid, *pAUX_rgid;
1.18      ws        443:        const AuxInfo  *pAUX_pagesz;
1.134     joerg     444:        char          **env, **oenvp;
1.15      christos  445:        const AuxInfo  *auxp;
1.139     joerg     446:        Obj_Entry      *obj;
1.39      mycroft   447:        Elf_Addr       *const osp = sp;
1.15      christos  448:        bool            bind_now = 0;
1.134     joerg     449:        const char     *ld_bind_now, *ld_preload, *ld_library_path;
1.15      christos  450:        const char    **argv;
1.114     christos  451:        const char     *execname;
1.40      mycroft   452:        long            argc;
1.31      erh       453:        const char **real___progname;
1.34      christos  454:        const Obj_Entry **real___mainprog_obj;
1.31      erh       455:        char ***real_environ;
1.148     joerg     456:        sigset_t        mask;
1.134     joerg     457: #ifdef DEBUG
1.138     pooka     458:        const char     *ld_debug;
                    459: #endif
                    460: #ifdef RTLD_DEBUG
1.117     ad        461:        int i = 0;
1.12      christos  462: #endif
1.1       cgd       463:
1.15      christos  464:        /*
                    465:          * On entry, the dynamic linker itself has not been relocated yet.
                    466:          * Be very careful not to reference any global data until after
                    467:          * _rtld_init has returned.  It is OK to reference file-scope statics
                    468:          * and string constants, and to call static and global functions.
                    469:          */
                    470:        /* Find the auxiliary vector on the stack. */
                    471:        /* first Elf_Word reserved to address of exit routine */
1.60      mycroft   472: #if defined(RTLD_DEBUG)
1.75      mycroft   473:        debug = 1;
1.88      fvdl      474:        dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp,
                    475:            (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase));
1.164     skrll     476: #ifndef __x86_64__
1.75      mycroft   477:        dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_,
                    478:            &_DYNAMIC));
1.152     christos  479: #endif
1.162     matt      480: #endif
1.1       cgd       481:
1.15      christos  482:        sp += 2;                /* skip over return argument space */
                    483:        argv = (const char **) &sp[1];
1.40      mycroft   484:        argc = *(long *)sp;
1.39      mycroft   485:        sp += 2 + argc;         /* Skip over argc, arguments, and NULL
1.15      christos  486:                                 * terminator */
                    487:        env = (char **) sp;
                    488:        while (*sp++ != 0) {    /* Skip over environment, and NULL terminator */
1.60      mycroft   489: #if defined(RTLD_DEBUG)
1.71      junyoung  490:                dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1]));
1.1       cgd       491: #endif
1.15      christos  492:        }
1.156     joerg     493:        auxinfo = (AuxInfo *) sp;
1.1       cgd       494:
1.15      christos  495:        pAUX_base = pAUX_entry = pAUX_execfd = NULL;
                    496:        pAUX_phdr = pAUX_phent = pAUX_phnum = NULL;
1.53      christos  497:        pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL;
1.18      ws        498:        pAUX_pagesz = NULL;
1.44      pk        499:
1.114     christos  500:        execname = NULL;
                    501:
1.69      mycroft   502:        /* Digest the auxiliary vector. */
1.156     joerg     503:        for (auxp = auxinfo; auxp->a_type != AT_NULL; ++auxp) {
1.24      kleink    504:                switch (auxp->a_type) {
                    505:                case AT_BASE:
1.15      christos  506:                        pAUX_base = auxp;
                    507:                        break;
1.24      kleink    508:                case AT_ENTRY:
1.15      christos  509:                        pAUX_entry = auxp;
                    510:                        break;
1.24      kleink    511:                case AT_EXECFD:
1.15      christos  512:                        pAUX_execfd = auxp;
                    513:                        break;
1.24      kleink    514:                case AT_PHDR:
1.15      christos  515:                        pAUX_phdr = auxp;
                    516:                        break;
1.24      kleink    517:                case AT_PHENT:
1.15      christos  518:                        pAUX_phent = auxp;
                    519:                        break;
1.24      kleink    520:                case AT_PHNUM:
1.15      christos  521:                        pAUX_phnum = auxp;
                    522:                        break;
1.54      mycroft   523: #ifdef AT_EUID
1.53      christos  524:                case AT_EUID:
                    525:                        pAUX_euid = auxp;
                    526:                        break;
                    527:                case AT_RUID:
                    528:                        pAUX_ruid = auxp;
                    529:                        break;
                    530:                case AT_EGID:
                    531:                        pAUX_egid = auxp;
                    532:                        break;
                    533:                case AT_RGID:
                    534:                        pAUX_rgid = auxp;
                    535:                        break;
1.54      mycroft   536: #endif
1.114     christos  537: #ifdef AT_SUN_EXECNAME
                    538:                case AT_SUN_EXECNAME:
                    539:                        execname = (const char *)(const void *)auxp->a_v;
                    540:                        break;
                    541: #endif
1.24      kleink    542:                case AT_PAGESZ:
1.18      ws        543:                        pAUX_pagesz = auxp;
                    544:                        break;
1.15      christos  545:                }
                    546:        }
1.18      ws        547:
1.69      mycroft   548:        /* Initialize and relocate ourselves. */
1.90      junyoung  549:        if (pAUX_base == NULL) {
                    550:                _rtld_error("Bad pAUX_base");
                    551:                _rtld_die();
                    552:        }
1.69      mycroft   553:        assert(pAUX_pagesz != NULL);
1.24      kleink    554:        _rtld_pagesz = (int)pAUX_pagesz->a_v;
1.114     christos  555:        _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase, execname);
1.1       cgd       556:
1.15      christos  557:        __progname = _rtld_objself.path;
                    558:        environ = env;
1.1       cgd       559:
1.53      christos  560:        _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) ==
                    561:            (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) &&
                    562:            ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) ==
                    563:            (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid()));
1.1       cgd       564:
1.134     joerg     565: #ifdef DEBUG
                    566:        ld_debug = NULL;
                    567: #endif
                    568:        ld_bind_now = NULL;
                    569:        ld_library_path = NULL;
                    570:        ld_preload = NULL;
                    571:        /*
                    572:         * Inline avoid using normal getenv/unsetenv here as the libc
                    573:         * code is quite a bit more complicated.
                    574:         */
                    575:        for (oenvp = env; *env != NULL; ++env) {
                    576:                static const char bind_var[] = "LD_BIND_NOW=";
                    577:                static const char debug_var[] =  "LD_DEBUG=";
                    578:                static const char path_var[] = "LD_LIBRARY_PATH=";
                    579:                static const char preload_var[] = "LD_PRELOAD=";
                    580: #define LEN(x) (sizeof(x) - 1)
                    581:
                    582:                if ((*env)[0] != 'L' || (*env)[1] != 'D') {
                    583:                        /*
                    584:                         * Special case to skip most entries without
                    585:                         * the more expensive calls to strncmp.
                    586:                         */
                    587:                        *oenvp++ = *env;
                    588:                } else if (strncmp(*env, debug_var, LEN(debug_var)) == 0) {
                    589:                        if (_rtld_trust) {
                    590: #ifdef DEBUG
                    591:                                ld_debug = *env + LEN(debug_var);
                    592: #endif
                    593:                                *oenvp++ = *env;
                    594:                        }
                    595:                } else if (strncmp(*env, bind_var, LEN(bind_var)) == 0) {
1.173     joerg     596:                        if (_rtld_trust) {
                    597:                                ld_bind_now = *env + LEN(bind_var);
                    598:                                *oenvp++ = *env;
                    599:                        }
1.134     joerg     600:                } else if (strncmp(*env, path_var, LEN(path_var)) == 0) {
                    601:                        if (_rtld_trust) {
                    602:                                ld_library_path = *env + LEN(path_var);
                    603:                                *oenvp++ = *env;
                    604:                        }
                    605:                } else if (strncmp(*env, preload_var, LEN(preload_var)) == 0) {
                    606:                        if (_rtld_trust) {
                    607:                                ld_preload = *env + LEN(preload_var);
                    608:                                *oenvp++ = *env;
                    609:                        }
                    610:                } else {
                    611:                        *oenvp++ = *env;
                    612:                }
                    613: #undef LEN
                    614:        }
                    615:        *oenvp++ = NULL;
                    616:
1.15      christos  617:        if (ld_bind_now != NULL && *ld_bind_now != '\0')
                    618:                bind_now = true;
                    619:        if (_rtld_trust) {
1.6       mhitch    620: #ifdef DEBUG
1.75      mycroft   621: #ifdef RTLD_DEBUG
                    622:                debug = 0;
                    623: #endif
1.15      christos  624:                if (ld_debug != NULL && *ld_debug != '\0')
                    625:                        debug = 1;
                    626: #endif
1.134     joerg     627:                _rtld_add_paths(execname, &_rtld_paths, ld_library_path);
1.111     christos  628:        } else {
1.115     christos  629:                execname = NULL;
1.15      christos  630:        }
1.114     christos  631:        _rtld_process_hints(execname, &_rtld_paths, &_rtld_xforms,
1.113     christos  632:            _PATH_LD_HINTS);
1.66      junyoung  633:        dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p",
1.58      mycroft   634:             _rtld_objself.mapbase, _rtld_objself.relocbase));
1.15      christos  635:
                    636:        /*
                    637:          * Load the main program, or process its program header if it is
                    638:          * already loaded.
                    639:          */
                    640:        if (pAUX_execfd != NULL) {      /* Load the main program. */
1.24      kleink    641:                int             fd = pAUX_execfd->a_v;
1.110     christos  642:                const char *obj_name = argv[0] ? argv[0] : "main program";
1.15      christos  643:                dbg(("loading main program"));
1.110     christos  644:                _rtld_objmain = _rtld_map_object(obj_name, fd, NULL);
1.15      christos  645:                close(fd);
                    646:                if (_rtld_objmain == NULL)
                    647:                        _rtld_die();
                    648:        } else {                /* Main program already loaded. */
                    649:                const Elf_Phdr *phdr;
                    650:                int             phnum;
                    651:                caddr_t         entry;
                    652:
                    653:                dbg(("processing main program's program header"));
                    654:                assert(pAUX_phdr != NULL);
1.24      kleink    655:                phdr = (const Elf_Phdr *) pAUX_phdr->a_v;
1.15      christos  656:                assert(pAUX_phnum != NULL);
1.24      kleink    657:                phnum = pAUX_phnum->a_v;
1.15      christos  658:                assert(pAUX_phent != NULL);
1.24      kleink    659:                assert(pAUX_phent->a_v == sizeof(Elf_Phdr));
1.15      christos  660:                assert(pAUX_entry != NULL);
1.24      kleink    661:                entry = (caddr_t) pAUX_entry->a_v;
1.15      christos  662:                _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
1.84      mycroft   663:                _rtld_objmain->path = xstrdup(argv[0] ? argv[0] :
                    664:                    "main program");
1.89      junyoung  665:                _rtld_objmain->pathlen = strlen(_rtld_objmain->path);
1.15      christos  666:        }
                    667:
1.92      mycroft   668:        _rtld_objmain->mainprog = true;
1.165     skrll     669:
1.25      mycroft   670:        /*
                    671:         * Get the actual dynamic linker pathname from the executable if
                    672:         * possible.  (It should always be possible.)  That ensures that
                    673:         * gdb will find the right dynamic linker even if a non-standard
                    674:         * one is being used.
                    675:         */
                    676:        if (_rtld_objmain->interp != NULL &&
1.171     skrll     677:            strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0) {
1.25      mycroft   678:                _rtld_objself.path = xstrdup(_rtld_objmain->interp);
1.171     skrll     679:                _rtld_objself.pathlen = strlen(_rtld_objself.path);
                    680:        }
1.66      junyoung  681:        dbg(("actual dynamic linker is %s", _rtld_objself.path));
1.165     skrll     682:
1.114     christos  683:        _rtld_digest_dynamic(execname, _rtld_objmain);
1.15      christos  684:
1.84      mycroft   685:        /* Link the main program into the list of objects. */
                    686:        *_rtld_objtail = _rtld_objmain;
                    687:        _rtld_objtail = &_rtld_objmain->next;
1.131     skrll     688:        _rtld_objcount++;
                    689:        _rtld_objloads++;
1.84      mycroft   690:
1.15      christos  691:        _rtld_linkmap_add(_rtld_objmain);
1.178     christos  692:        _rtld_objself.path = xstrdup(_rtld_objself.path);
1.15      christos  693:        _rtld_linkmap_add(&_rtld_objself);
                    694:
                    695:        ++_rtld_objmain->refcount;
1.84      mycroft   696:        _rtld_objmain->mainref = 1;
1.117     ad        697:        _rtld_objlist_push_tail(&_rtld_list_main, _rtld_objmain);
1.19      kleink    698:
1.134     joerg     699:        if (ld_preload) {
1.111     christos  700:                /*
                    701:                 * Pre-load user-specified objects after the main program
                    702:                 * but before any shared object dependencies.
                    703:                 */
                    704:                dbg(("preloading objects"));
1.134     joerg     705:                if (_rtld_preload(ld_preload) == -1)
1.127     christos  706:                        _rtld_die();
1.134     joerg     707:        }
1.15      christos  708:
                    709:        dbg(("loading needed objects"));
1.137     skrll     710:        if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1)
1.15      christos  711:                _rtld_die();
                    712:
1.151     nonaka    713:        dbg(("checking for required versions"));
                    714:        for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
                    715:                if (_rtld_verify_object_versions(obj) == -1)
                    716:                        _rtld_die();
                    717:        }
                    718:
1.139     joerg     719: #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
1.154     joerg     720:        dbg(("initializing initial Thread Local Storage offsets"));
1.139     joerg     721:        /*
                    722:         * All initial objects get the TLS space from the static block.
                    723:         */
                    724:        for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
                    725:                _rtld_tls_offset_allocate(obj);
                    726: #endif
                    727:
1.15      christos  728:        dbg(("relocating objects"));
1.81      mycroft   729:        if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1)
1.15      christos  730:                _rtld_die();
                    731:
                    732:        dbg(("doing copy relocations"));
1.60      mycroft   733:        if (_rtld_do_copy_relocations(_rtld_objmain) == -1)
1.15      christos  734:                _rtld_die();
                    735:
1.154     joerg     736: #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
                    737:        dbg(("initializing Thread Local Storage for main thread"));
                    738:        /*
                    739:         * Set up TLS area for the main thread.
                    740:         * This has to be done after all relocations are processed,
                    741:         * since .tdata may contain relocations.
                    742:         */
                    743:        _rtld_tls_initial_allocation();
                    744: #endif
                    745:
1.31      erh       746:        /*
1.34      christos  747:         * Set the __progname,  environ and, __mainprog_obj before
                    748:         * calling anything that might use them.
1.31      erh       749:         */
                    750:        real___progname = _rtld_objmain_sym("__progname");
                    751:        if (real___progname) {
1.64      christos  752:                if (argv[0] != NULL) {
                    753:                        if ((*real___progname = strrchr(argv[0], '/')) == NULL)
                    754:                                (*real___progname) = argv[0];
                    755:                        else
                    756:                                (*real___progname)++;
                    757:                } else {
                    758:                        (*real___progname) = NULL;
                    759:                }
1.31      erh       760:        }
                    761:        real_environ = _rtld_objmain_sym("environ");
                    762:        if (real_environ)
                    763:                *real_environ = environ;
1.99      skrll     764:        /*
                    765:         * Set __mainprog_obj for old binaries.
                    766:         */
1.34      christos  767:        real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj");
                    768:        if (real___mainprog_obj)
                    769:                *real___mainprog_obj = _rtld_objmain;
1.31      erh       770:
1.184     joerg     771:        _rtld_debug_state();    /* say hello to gdb! */
                    772:
1.148     joerg     773:        _rtld_exclusive_enter(&mask);
1.141     joerg     774:
1.15      christos  775:        dbg(("calling _init functions"));
1.148     joerg     776:        _rtld_call_init_functions(&mask);
1.15      christos  777:
                    778:        dbg(("control at program entry point = %p, obj = %p, exit = %p",
                    779:             _rtld_objmain->entry, _rtld_objmain, _rtld_exit));
                    780:
1.148     joerg     781:        _rtld_exclusive_exit(&mask);
1.141     joerg     782:
1.15      christos  783:        /*
                    784:         * Return with the entry point and the exit procedure in at the top
                    785:         * of stack.
                    786:         */
                    787:
                    788:        ((void **) osp)[0] = _rtld_exit;
1.190.2.3  pgoyette  789:        ((void **) osp)[1] = __UNCONST(_rtld_compat_obj);
1.15      christos  790:        return (Elf_Addr) _rtld_objmain->entry;
1.1       cgd       791: }
                    792:
                    793: void
1.98      skrll     794: _rtld_die(void)
1.1       cgd       795: {
1.99      skrll     796:        const char *msg = dlerror();
1.1       cgd       797:
1.15      christos  798:        if (msg == NULL)
                    799:                msg = "Fatal error";
1.52      soren     800:        xerrx(1, "%s", msg);
1.1       cgd       801: }
                    802:
                    803: static Obj_Entry *
1.98      skrll     804: _rtld_dlcheck(void *handle)
1.1       cgd       805: {
1.15      christos  806:        Obj_Entry *obj;
1.1       cgd       807:
1.15      christos  808:        for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
                    809:                if (obj == (Obj_Entry *) handle)
                    810:                        break;
                    811:
                    812:        if (obj == NULL || obj->dl_refcount == 0) {
1.159     riastrad  813:                _rtld_error("Invalid shared object handle %p", handle);
1.15      christos  814:                return NULL;
                    815:        }
                    816:        return obj;
1.1       cgd       817: }
                    818:
                    819: static void
1.117     ad        820: _rtld_initlist_visit(Objlist* list, Obj_Entry *obj, int rev)
                    821: {
                    822:        Needed_Entry* elm;
                    823:
                    824:        /* dbg(("_rtld_initlist_visit(%s)", obj->path)); */
                    825:
                    826:        if (obj->init_done)
                    827:                return;
                    828:        obj->init_done = 1;
                    829:
                    830:        for (elm = obj->needed; elm != NULL; elm = elm->next) {
                    831:                if (elm->obj != NULL) {
                    832:                        _rtld_initlist_visit(list, elm->obj, rev);
                    833:                }
                    834:        }
                    835:
                    836:        if (rev) {
                    837:                _rtld_objlist_push_head(list, obj);
                    838:        } else {
                    839:                _rtld_objlist_push_tail(list, obj);
                    840:        }
                    841: }
                    842:
                    843: static void
                    844: _rtld_initlist_tsort(Objlist* list, int rev)
                    845: {
                    846:        dbg(("_rtld_initlist_tsort"));
                    847:
                    848:        Obj_Entry* obj;
                    849:
1.190.2.4! pgoyette  850:        /*
        !           851:         * We don't include objmain here (starting from next)
        !           852:         * because csu handles it
        !           853:         */
1.117     ad        854:        for (obj = _rtld_objlist->next; obj; obj = obj->next) {
                    855:                obj->init_done = 0;
                    856:        }
                    857:
                    858:        for (obj = _rtld_objlist->next; obj; obj = obj->next) {
                    859:                _rtld_initlist_visit(list, obj, rev);
                    860:        }
                    861: }
                    862:
                    863: static void
1.98      skrll     864: _rtld_init_dag(Obj_Entry *root)
1.25      mycroft   865: {
1.94      simonb    866:
1.25      mycroft   867:        _rtld_init_dag1(root, root);
                    868: }
                    869:
                    870: static void
1.98      skrll     871: _rtld_init_dag1(Obj_Entry *root, Obj_Entry *obj)
1.25      mycroft   872: {
                    873:        const Needed_Entry *needed;
                    874:
1.84      mycroft   875:        if (!obj->mainref) {
                    876:                if (_rtld_objlist_find(&obj->dldags, root))
                    877:                        return;
1.133     skrll     878:                dbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root,
1.84      mycroft   879:                    root->path));
1.117     ad        880:                _rtld_objlist_push_tail(&obj->dldags, root);
                    881:                _rtld_objlist_push_tail(&root->dagmembers, obj);
1.84      mycroft   882:        }
1.25      mycroft   883:        for (needed = obj->needed; needed != NULL; needed = needed->next)
                    884:                if (needed->obj != NULL)
                    885:                        _rtld_init_dag1(root, needed->obj);
                    886: }
                    887:
                    888: /*
                    889:  * Note, this is called only for objects loaded by dlopen().
                    890:  */
                    891: static void
1.148     joerg     892: _rtld_unload_object(sigset_t *mask, Obj_Entry *root, bool do_fini_funcs)
1.25      mycroft   893: {
1.94      simonb    894:
1.25      mycroft   895:        _rtld_unref_dag(root);
                    896:        if (root->refcount == 0) { /* We are finished with some objects. */
                    897:                Obj_Entry *obj;
                    898:                Obj_Entry **linkp;
                    899:                Objlist_Entry *elm;
                    900:
                    901:                /* Finalize objects that are about to be unmapped. */
                    902:                if (do_fini_funcs)
1.148     joerg     903:                        _rtld_call_fini_functions(mask, 0);
1.25      mycroft   904:
                    905:                /* Remove the DAG from all objects' DAG lists. */
1.50      lukem     906:                SIMPLEQ_FOREACH(elm, &root->dagmembers, link)
1.25      mycroft   907:                        _rtld_objlist_remove(&elm->obj->dldags, root);
                    908:
                    909:                /* Remove the DAG from the RTLD_GLOBAL list. */
1.84      mycroft   910:                if (root->globalref) {
                    911:                        root->globalref = 0;
                    912:                        _rtld_objlist_remove(&_rtld_list_global, root);
                    913:                }
1.25      mycroft   914:
                    915:                /* Unmap all objects that are no longer referenced. */
                    916:                linkp = &_rtld_objlist->next;
                    917:                while ((obj = *linkp) != NULL) {
                    918:                        if (obj->refcount == 0) {
                    919:                                dbg(("unloading \"%s\"", obj->path));
1.118     ad        920:                                if (obj->ehdr != MAP_FAILED)
                    921:                                        munmap(obj->ehdr, _rtld_pagesz);
1.25      mycroft   922:                                munmap(obj->mapbase, obj->mapsize);
1.45      christos  923:                                _rtld_objlist_remove(&_rtld_list_global, obj);
1.25      mycroft   924:                                _rtld_linkmap_delete(obj);
                    925:                                *linkp = obj->next;
1.129     roy       926:                                _rtld_objcount--;
1.25      mycroft   927:                                _rtld_obj_free(obj);
                    928:                        } else
                    929:                                linkp = &obj->next;
                    930:                }
                    931:                _rtld_objtail = linkp;
                    932:        }
                    933: }
                    934:
1.137     skrll     935: void
                    936: _rtld_ref_dag(Obj_Entry *root)
                    937: {
                    938:        const Needed_Entry *needed;
                    939:
                    940:        assert(root);
                    941:
                    942:        ++root->refcount;
                    943:
                    944:        dbg(("incremented reference on \"%s\" (%d)", root->path,
                    945:            root->refcount));
                    946:        for (needed = root->needed; needed != NULL;
                    947:             needed = needed->next) {
                    948:                if (needed->obj != NULL)
                    949:                        _rtld_ref_dag(needed->obj);
                    950:        }
                    951: }
                    952:
1.25      mycroft   953: static void
1.98      skrll     954: _rtld_unref_dag(Obj_Entry *root)
1.1       cgd       955: {
1.94      simonb    956:
1.33      jdolecek  957:        assert(root);
1.15      christos  958:        assert(root->refcount != 0);
1.137     skrll     959:
1.15      christos  960:        --root->refcount;
1.137     skrll     961:        dbg(("decremented reference on \"%s\" (%d)", root->path,
                    962:            root->refcount));
                    963:
1.15      christos  964:        if (root->refcount == 0) {
                    965:                const Needed_Entry *needed;
                    966:
                    967:                for (needed = root->needed; needed != NULL;
1.32      jdolecek  968:                     needed = needed->next) {
                    969:                        if (needed->obj != NULL)
                    970:                                _rtld_unref_dag(needed->obj);
                    971:                }
1.15      christos  972:        }
1.1       cgd       973: }
                    974:
1.106     thorpej   975: __strong_alias(__dlclose,dlclose)
1.1       cgd       976: int
1.99      skrll     977: dlclose(void *handle)
1.1       cgd       978: {
1.143     joerg     979:        Obj_Entry *root;
1.148     joerg     980:        sigset_t mask;
1.1       cgd       981:
1.144     joerg     982:        dbg(("dlclose of %p", handle));
1.143     joerg     983:
1.148     joerg     984:        _rtld_exclusive_enter(&mask);
1.143     joerg     985:
                    986:        root = _rtld_dlcheck(handle);
                    987:
                    988:        if (root == NULL) {
1.148     joerg     989:                _rtld_exclusive_exit(&mask);
1.15      christos  990:                return -1;
1.143     joerg     991:        }
1.1       cgd       992:
1.15      christos  993:        _rtld_debug.r_state = RT_DELETE;
                    994:        _rtld_debug_state();
                    995:
                    996:        --root->dl_refcount;
1.148     joerg     997:        _rtld_unload_object(&mask, root, true);
1.15      christos  998:
                    999:        _rtld_debug.r_state = RT_CONSISTENT;
                   1000:        _rtld_debug_state();
1.1       cgd      1001:
1.148     joerg    1002:        _rtld_exclusive_exit(&mask);
1.143     joerg    1003:
1.15      christos 1004:        return 0;
1.1       cgd      1005: }
                   1006:
1.106     thorpej  1007: __strong_alias(__dlerror,dlerror)
1.1       cgd      1008: char *
1.99      skrll    1009: dlerror(void)
1.1       cgd      1010: {
1.15      christos 1011:        char *msg = error_message;
1.94      simonb   1012:
1.15      christos 1013:        error_message = NULL;
                   1014:        return msg;
1.1       cgd      1015: }
                   1016:
1.106     thorpej  1017: __strong_alias(__dlopen,dlopen)
1.1       cgd      1018: void *
1.99      skrll    1019: dlopen(const char *name, int mode)
1.15      christos 1020: {
                   1021:        Obj_Entry **old_obj_tail = _rtld_objtail;
                   1022:        Obj_Entry *obj = NULL;
1.137     skrll    1023:        int flags = _RTLD_DLOPEN;
                   1024:        bool nodelete;
                   1025:        bool now;
1.148     joerg    1026:        sigset_t mask;
1.151     nonaka   1027:        int result;
1.137     skrll    1028:
1.144     joerg    1029:        dbg(("dlopen of %s %d", name, mode));
                   1030:
1.148     joerg    1031:        _rtld_exclusive_enter(&mask);
1.141     joerg    1032:
1.137     skrll    1033:        flags |= (mode & RTLD_GLOBAL) ? _RTLD_GLOBAL : 0;
                   1034:        flags |= (mode & RTLD_NOLOAD) ? _RTLD_NOLOAD : 0;
1.165     skrll    1035:
1.137     skrll    1036:        nodelete = (mode & RTLD_NODELETE) ? true : false;
                   1037:        now = ((mode & RTLD_MODEMASK) == RTLD_NOW) ? true : false;
1.15      christos 1038:
                   1039:        _rtld_debug.r_state = RT_ADD;
                   1040:        _rtld_debug_state();
                   1041:
                   1042:        if (name == NULL) {
                   1043:                obj = _rtld_objmain;
1.25      mycroft  1044:                obj->refcount++;
1.67      mycroft  1045:        } else
1.137     skrll    1046:                obj = _rtld_load_library(name, _rtld_objmain, flags);
                   1047:
1.1       cgd      1048:
1.15      christos 1049:        if (obj != NULL) {
                   1050:                ++obj->dl_refcount;
                   1051:                if (*old_obj_tail != NULL) {    /* We loaded something new. */
                   1052:                        assert(*old_obj_tail == obj);
                   1053:
1.151     nonaka   1054:                        result = _rtld_load_needed_objects(obj, flags);
                   1055:                        if (result != -1) {
                   1056:                                Objlist_Entry *entry;
                   1057:                                _rtld_init_dag(obj);
                   1058:                                SIMPLEQ_FOREACH(entry, &obj->dagmembers, link) {
                   1059:                                        result = _rtld_verify_object_versions(entry->obj);
                   1060:                                        if (result == -1)
                   1061:                                                break;
                   1062:                                }
                   1063:                        }
                   1064:                        if (result == -1 || _rtld_relocate_objects(obj,
                   1065:                            (now || obj->z_now)) == -1) {
1.148     joerg    1066:                                _rtld_unload_object(&mask, obj, false);
1.25      mycroft  1067:                                obj->dl_refcount--;
1.15      christos 1068:                                obj = NULL;
1.117     ad       1069:                        } else {
1.148     joerg    1070:                                _rtld_call_init_functions(&mask);
1.117     ad       1071:                        }
1.15      christos 1072:                }
1.137     skrll    1073:                if (obj != NULL) {
                   1074:                        if ((nodelete || obj->z_nodelete) && !obj->ref_nodel) {
                   1075:                                dbg(("dlopen obj %s nodelete", obj->path));
                   1076:                                _rtld_ref_dag(obj);
                   1077:                                obj->z_nodelete = obj->ref_nodel = true;
                   1078:                        }
                   1079:                }
1.15      christos 1080:        }
                   1081:        _rtld_debug.r_state = RT_CONSISTENT;
                   1082:        _rtld_debug_state();
1.1       cgd      1083:
1.148     joerg    1084:        _rtld_exclusive_exit(&mask);
1.141     joerg    1085:
1.15      christos 1086:        return obj;
1.31      erh      1087: }
                   1088:
                   1089: /*
                   1090:  * Find a symbol in the main program.
                   1091:  */
                   1092: void *
1.98      skrll    1093: _rtld_objmain_sym(const char *name)
1.31      erh      1094: {
                   1095:        unsigned long hash;
                   1096:        const Elf_Sym *def;
                   1097:        const Obj_Entry *obj;
1.129     roy      1098:        DoneList donelist;
1.31      erh      1099:
                   1100:        hash = _rtld_elf_hash(name);
                   1101:        obj = _rtld_objmain;
1.129     roy      1102:        _rtld_donelist_init(&donelist);
1.31      erh      1103:
1.151     nonaka   1104:        def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, 0,
                   1105:            NULL, &donelist);
1.129     roy      1106:
1.31      erh      1107:        if (def != NULL)
                   1108:                return obj->relocbase + def->st_value;
1.136     skrll    1109:        return NULL;
1.1       cgd      1110: }
                   1111:
1.121     macallan 1112: #ifdef __powerpc__
1.183     chs      1113: static __noinline void *
1.121     macallan 1114: hackish_return_address(void)
                   1115: {
1.190     jakllsch 1116: #if __GNUC_PREREQ__(6,0)
1.189     mrg      1117: #pragma GCC diagnostic push
                   1118: #pragma GCC diagnostic ignored "-Wframe-address"
1.190     jakllsch 1119: #endif
1.121     macallan 1120:        return __builtin_return_address(1);
1.190     jakllsch 1121: #if __GNUC_PREREQ__(6,0)
1.189     mrg      1122: #pragma GCC diagnostic pop
1.190     jakllsch 1123: #endif
1.121     macallan 1124: }
                   1125: #endif
                   1126:
1.141     joerg    1127: #ifdef __HAVE_FUNCTION_DESCRIPTORS
1.148     joerg    1128: #define        lookup_mutex_enter()    _rtld_exclusive_enter(&mask)
                   1129: #define        lookup_mutex_exit()     _rtld_exclusive_exit(&mask)
1.141     joerg    1130: #else
                   1131: #define        lookup_mutex_enter()    _rtld_shared_enter()
                   1132: #define        lookup_mutex_exit()     _rtld_shared_exit()
                   1133: #endif
                   1134:
1.151     nonaka   1135: static void *
1.155     joerg    1136: do_dlsym(void *handle, const char *name, const Ver_Entry *ventry, void *retaddr)
1.15      christos 1137: {
1.25      mycroft  1138:        const Obj_Entry *obj;
1.92      mycroft  1139:        unsigned long hash;
1.25      mycroft  1140:        const Elf_Sym *def;
1.15      christos 1141:        const Obj_Entry *defobj;
1.148     joerg    1142:        DoneList donelist;
1.151     nonaka   1143:        const u_int flags = SYMLOOK_DLSYM | SYMLOOK_IN_PLT;
1.148     joerg    1144: #ifdef __HAVE_FUNCTION_DESCRIPTORS
                   1145:        sigset_t mask;
                   1146: #endif
1.141     joerg    1147:
                   1148:        lookup_mutex_enter();
                   1149:
1.92      mycroft  1150:        hash = _rtld_elf_hash(name);
                   1151:        def = NULL;
                   1152:        defobj = NULL;
1.165     skrll    1153:
1.93      christos 1154:        switch ((intptr_t)handle) {
                   1155:        case (intptr_t)NULL:
                   1156:        case (intptr_t)RTLD_NEXT:
                   1157:        case (intptr_t)RTLD_DEFAULT:
                   1158:        case (intptr_t)RTLD_SELF:
1.30      christos 1159:                if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
                   1160:                        _rtld_error("Cannot determine caller's shared object");
1.141     joerg    1161:                        lookup_mutex_exit();
1.30      christos 1162:                        return NULL;
                   1163:                }
1.93      christos 1164:
                   1165:                switch ((intptr_t)handle) {
                   1166:                case (intptr_t)NULL:     /* Just the caller's shared object. */
1.151     nonaka   1167:                        def = _rtld_symlook_obj(name, hash, obj, flags, ventry);
1.92      mycroft  1168:                        defobj = obj;
1.93      christos 1169:                        break;
                   1170:
                   1171:                case (intptr_t)RTLD_NEXT:       /* Objects after callers */
                   1172:                        obj = obj->next;
                   1173:                        /*FALLTHROUGH*/
                   1174:
                   1175:                case (intptr_t)RTLD_SELF:       /* Caller included */
                   1176:                        for (; obj; obj = obj->next) {
                   1177:                                if ((def = _rtld_symlook_obj(name, hash, obj,
1.151     nonaka   1178:                                    flags, ventry)) != NULL) {
1.92      mycroft  1179:                                        defobj = obj;
                   1180:                                        break;
                   1181:                                }
                   1182:                        }
1.179     christos 1183:                        /*
1.180     christos 1184:                         * Search the dynamic linker itself, and possibly
                   1185:                         * resolve the symbol from there if it is not defined
1.179     christos 1186:                         * already or weak. This is how the application links
1.181     christos 1187:                         * to dynamic linker services such as dlopen.
1.179     christos 1188:                         */
                   1189:                        if (!def || ELF_ST_BIND(def->st_info) == STB_WEAK) {
                   1190:                                const Elf_Sym *symp = _rtld_symlook_obj(name,
                   1191:                                    hash, &_rtld_objself, flags, ventry);
1.181     christos 1192:                                if (symp != NULL) {
1.179     christos 1193:                                        def = symp;
                   1194:                                        defobj = &_rtld_objself;
                   1195:                                }
                   1196:                        }
1.93      christos 1197:                        break;
                   1198:
                   1199:                case (intptr_t)RTLD_DEFAULT:
                   1200:                        def = _rtld_symlook_default(name, hash, obj, &defobj,
1.151     nonaka   1201:                            flags, ventry);
1.93      christos 1202:                        break;
                   1203:
                   1204:                default:
                   1205:                        abort();
1.92      mycroft  1206:                }
1.93      christos 1207:                break;
                   1208:
                   1209:        default:
1.141     joerg    1210:                if ((obj = _rtld_dlcheck(handle)) == NULL) {
                   1211:                        lookup_mutex_exit();
1.30      christos 1212:                        return NULL;
1.141     joerg    1213:                }
                   1214:
1.129     roy      1215:                _rtld_donelist_init(&donelist);
                   1216:
1.92      mycroft  1217:                if (obj->mainprog) {
1.93      christos 1218:                        /* Search main program and all libraries loaded by it */
                   1219:                        def = _rtld_symlook_list(name, hash, &_rtld_list_main,
1.151     nonaka   1220:                            &defobj, flags, ventry, &donelist);
1.92      mycroft  1221:                } else {
1.122     skrll    1222:                        Needed_Entry fake;
1.129     roy      1223:                        DoneList depth;
1.122     skrll    1224:
                   1225:                        /* Search the object and all the libraries loaded by it. */
                   1226:                        fake.next = NULL;
1.124     christos 1227:                        fake.obj = __UNCONST(obj);
1.122     skrll    1228:                        fake.name = 0;
1.129     roy      1229:
                   1230:                        _rtld_donelist_init(&depth);
1.122     skrll    1231:                        def = _rtld_symlook_needed(name, hash, &fake, &defobj,
1.151     nonaka   1232:                            flags, ventry, &donelist, &depth);
1.25      mycroft  1233:                }
1.129     roy      1234:
1.93      christos 1235:                break;
1.30      christos 1236:        }
1.165     skrll    1237:
1.51      fredette 1238:        if (def != NULL) {
1.141     joerg    1239:                void *p;
1.174     joerg    1240:
                   1241:                if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
                   1242: #ifdef __HAVE_FUNCTION_DESCRIPTORS
                   1243:                        lookup_mutex_exit();
                   1244:                        _rtld_shared_enter();
                   1245: #endif
                   1246:                        p = (void *)_rtld_resolve_ifunc(defobj, def);
                   1247:                        _rtld_shared_exit();
                   1248:                        return p;
                   1249:                }
                   1250:
1.51      fredette 1251: #ifdef __HAVE_FUNCTION_DESCRIPTORS
1.141     joerg    1252:                if (ELF_ST_TYPE(def->st_info) == STT_FUNC) {
1.142     joerg    1253:                        p = (void *)_rtld_function_descriptor_alloc(defobj,
                   1254:                            def, 0);
1.141     joerg    1255:                        lookup_mutex_exit();
                   1256:                        return p;
                   1257:                }
1.51      fredette 1258: #endif /* __HAVE_FUNCTION_DESCRIPTORS */
1.141     joerg    1259:                p = defobj->relocbase + def->st_value;
                   1260:                lookup_mutex_exit();
                   1261:                return p;
1.51      fredette 1262:        }
1.165     skrll    1263:
1.101     mycroft  1264:        _rtld_error("Undefined symbol \"%s\"", name);
1.141     joerg    1265:        lookup_mutex_exit();
1.92      mycroft  1266:        return NULL;
1.25      mycroft  1267: }
1.1       cgd      1268:
1.151     nonaka   1269: __strong_alias(__dlsym,dlsym)
                   1270: void *
                   1271: dlsym(void *handle, const char *name)
                   1272: {
1.155     joerg    1273:        void *retaddr;
1.151     nonaka   1274:
                   1275:        dbg(("dlsym of %s in %p", name, handle));
                   1276:
1.155     joerg    1277: #ifdef __powerpc__
                   1278:        retaddr = hackish_return_address();
                   1279: #else
                   1280:        retaddr = __builtin_return_address(0);
                   1281: #endif
                   1282:        return do_dlsym(handle, name, NULL, retaddr);
1.151     nonaka   1283: }
                   1284:
                   1285: __strong_alias(__dlvsym,dlvsym)
                   1286: void *
                   1287: dlvsym(void *handle, const char *name, const char *version)
                   1288: {
                   1289:        Ver_Entry *ventry = NULL;
                   1290:        Ver_Entry ver_entry;
1.155     joerg    1291:        void *retaddr;
1.151     nonaka   1292:
                   1293:        dbg(("dlvsym of %s@%s in %p", name, version ? version : NULL, handle));
                   1294:
                   1295:        if (version != NULL) {
                   1296:                ver_entry.name = version;
                   1297:                ver_entry.file = NULL;
                   1298:                ver_entry.hash = _rtld_elf_hash(version);
                   1299:                ver_entry.flags = 0;
                   1300:                ventry = &ver_entry;
                   1301:        }
1.155     joerg    1302: #ifdef __powerpc__
                   1303:        retaddr = hackish_return_address();
                   1304: #else
                   1305:        retaddr = __builtin_return_address(0);
                   1306: #endif
                   1307:        return do_dlsym(handle, name, ventry, retaddr);
1.151     nonaka   1308: }
                   1309:
1.106     thorpej  1310: __strong_alias(__dladdr,dladdr)
1.25      mycroft  1311: int
1.99      skrll    1312: dladdr(const void *addr, Dl_info *info)
1.25      mycroft  1313: {
                   1314:        const Obj_Entry *obj;
1.51      fredette 1315:        const Elf_Sym *def, *best_def;
1.25      mycroft  1316:        void *symbol_addr;
                   1317:        unsigned long symoffset;
1.149     joerg    1318: #ifdef __HAVE_FUNCTION_DESCRIPTORS
                   1319:        sigset_t mask;
                   1320: #endif
1.141     joerg    1321:
1.144     joerg    1322:        dbg(("dladdr of %p", addr));
                   1323:
1.141     joerg    1324:        lookup_mutex_enter();
                   1325:
1.51      fredette 1326: #ifdef __HAVE_FUNCTION_DESCRIPTORS
                   1327:        addr = _rtld_function_descriptor_function(addr);
                   1328: #endif /* __HAVE_FUNCTION_DESCRIPTORS */
                   1329:
1.25      mycroft  1330:        obj = _rtld_obj_from_addr(addr);
                   1331:        if (obj == NULL) {
                   1332:                _rtld_error("No shared object contains address");
1.176     joerg    1333:                lookup_mutex_exit();
1.25      mycroft  1334:                return 0;
                   1335:        }
                   1336:        info->dli_fname = obj->path;
                   1337:        info->dli_fbase = obj->mapbase;
                   1338:        info->dli_saddr = (void *)0;
                   1339:        info->dli_sname = NULL;
1.165     skrll    1340:
1.15      christos 1341:        /*
1.25      mycroft  1342:         * Walk the symbol list looking for the symbol whose address is
                   1343:         * closest to the address sent in.
                   1344:         */
1.51      fredette 1345:        best_def = NULL;
1.25      mycroft  1346:        for (symoffset = 0; symoffset < obj->nchains; symoffset++) {
                   1347:                def = obj->symtab + symoffset;
                   1348:
                   1349:                /*
                   1350:                 * For skip the symbol if st_shndx is either SHN_UNDEF or
                   1351:                 * SHN_COMMON.
                   1352:                 */
                   1353:                if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON)
                   1354:                        continue;
                   1355:
                   1356:                /*
                   1357:                 * If the symbol is greater than the specified address, or if it
                   1358:                 * is further away from addr than the current nearest symbol,
                   1359:                 * then reject it.
                   1360:                 */
                   1361:                symbol_addr = obj->relocbase + def->st_value;
                   1362:                if (symbol_addr > addr || symbol_addr < info->dli_saddr)
                   1363:                        continue;
                   1364:
                   1365:                /* Update our idea of the nearest symbol. */
                   1366:                info->dli_sname = obj->strtab + def->st_name;
                   1367:                info->dli_saddr = symbol_addr;
1.51      fredette 1368:                best_def = def;
1.1       cgd      1369:
1.170     christos 1370:
1.25      mycroft  1371:                /* Exact match? */
                   1372:                if (info->dli_saddr == addr)
                   1373:                        break;
                   1374:        }
1.51      fredette 1375:
                   1376: #ifdef __HAVE_FUNCTION_DESCRIPTORS
                   1377:        if (best_def != NULL && ELF_ST_TYPE(best_def->st_info) == STT_FUNC)
1.165     skrll    1378:                info->dli_saddr = (void *)_rtld_function_descriptor_alloc(obj,
1.51      fredette 1379:                    best_def, 0);
1.170     christos 1380: #else
                   1381:        __USE(best_def);
1.51      fredette 1382: #endif /* __HAVE_FUNCTION_DESCRIPTORS */
                   1383:
1.141     joerg    1384:        lookup_mutex_exit();
1.25      mycroft  1385:        return 1;
1.1       cgd      1386: }
                   1387:
1.125     pooka    1388: __strong_alias(__dlinfo,dlinfo)
                   1389: int
                   1390: dlinfo(void *handle, int req, void *v)
                   1391: {
                   1392:        const Obj_Entry *obj;
                   1393:        void *retaddr;
                   1394:
1.144     joerg    1395:        dbg(("dlinfo for %p %d", handle, req));
                   1396:
1.141     joerg    1397:        _rtld_shared_enter();
                   1398:
1.125     pooka    1399:        if (handle == RTLD_SELF) {
                   1400: #ifdef __powerpc__
                   1401:                retaddr = hackish_return_address();
                   1402: #else
                   1403:                retaddr = __builtin_return_address(0);
                   1404: #endif
                   1405:                if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
                   1406:                        _rtld_error("Cannot determine caller's shared object");
1.141     joerg    1407:                        _rtld_shared_exit();
1.125     pooka    1408:                        return -1;
                   1409:                }
                   1410:        } else {
                   1411:                if ((obj = _rtld_dlcheck(handle)) == NULL) {
1.141     joerg    1412:                        _rtld_shared_exit();
1.125     pooka    1413:                        return -1;
                   1414:                }
                   1415:        }
                   1416:
                   1417:        switch (req) {
                   1418:        case RTLD_DI_LINKMAP:
                   1419:                {
                   1420:                const struct link_map **map = v;
                   1421:
                   1422:                *map = &obj->linkmap;
                   1423:                break;
                   1424:                }
                   1425:
                   1426:        default:
                   1427:                _rtld_error("Invalid request");
1.141     joerg    1428:                _rtld_shared_exit();
1.125     pooka    1429:                return -1;
                   1430:        }
                   1431:
1.141     joerg    1432:        _rtld_shared_exit();
1.125     pooka    1433:        return 0;
                   1434: }
                   1435:
1.131     skrll    1436: __strong_alias(__dl_iterate_phdr,dl_iterate_phdr);
                   1437: int
                   1438: dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *param)
                   1439: {
                   1440:        struct dl_phdr_info phdr_info;
                   1441:        const Obj_Entry *obj;
                   1442:        int error = 0;
                   1443:
1.144     joerg    1444:        dbg(("dl_iterate_phdr"));
                   1445:
1.141     joerg    1446:        _rtld_shared_enter();
                   1447:
1.131     skrll    1448:        for (obj = _rtld_objlist;  obj != NULL;  obj = obj->next) {
                   1449:                phdr_info.dlpi_addr = (Elf_Addr)obj->relocbase;
1.166     christos 1450:                /* XXX: wrong but not fixing it yet */
1.182     christos 1451:                phdr_info.dlpi_name = obj->path;
1.131     skrll    1452:                phdr_info.dlpi_phdr = obj->phdr;
                   1453:                phdr_info.dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]);
1.140     joerg    1454: #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
                   1455:                phdr_info.dlpi_tls_modid = obj->tlsindex;
                   1456:                phdr_info.dlpi_tls_data = obj->tlsinit;
                   1457: #else
1.131     skrll    1458:                phdr_info.dlpi_tls_modid = 0;
                   1459:                phdr_info.dlpi_tls_data = 0;
                   1460: #endif
                   1461:                phdr_info.dlpi_adds = _rtld_objloads;
                   1462:                phdr_info.dlpi_subs = _rtld_objloads - _rtld_objcount;
                   1463:
1.141     joerg    1464:                /* XXXlocking: exit point */
1.131     skrll    1465:                error = callback(&phdr_info, sizeof(phdr_info), param);
                   1466:                if (error)
                   1467:                        break;
                   1468:        }
                   1469:
1.141     joerg    1470:        _rtld_shared_exit();
1.131     skrll    1471:        return error;
                   1472: }
                   1473:
1.185     joerg    1474: void
                   1475: __dl_cxa_refcount(void *addr, ssize_t delta)
                   1476: {
                   1477:        sigset_t mask;
                   1478:        Obj_Entry *obj;
                   1479:
                   1480:        if (delta == 0)
                   1481:                return;
                   1482:
                   1483:        dbg(("__dl_cxa_refcount of %p with %zd", addr, delta));
                   1484:
                   1485:        _rtld_exclusive_enter(&mask);
                   1486:        obj = _rtld_obj_from_addr(addr);
                   1487:
                   1488:        if (obj == NULL) {
                   1489:                dbg(("__dl_cxa_refcont: address not found"));
                   1490:                _rtld_error("No shared object contains address");
                   1491:                _rtld_exclusive_exit(&mask);
                   1492:                return;
                   1493:        }
                   1494:        if (delta > 0 && obj->cxa_refcount > SIZE_MAX - delta)
                   1495:                _rtld_error("Reference count overflow");
                   1496:        else if (delta < 0 && obj->cxa_refcount < -1 + (size_t)-(delta + 1))
                   1497:                _rtld_error("Reference count underflow");
                   1498:        else {
                   1499:                if (obj->cxa_refcount == 0)
                   1500:                        ++obj->refcount;
                   1501:                obj->cxa_refcount += delta;
                   1502:                dbg(("new reference count: %zu", obj->cxa_refcount));
                   1503:                if (obj->cxa_refcount == 0) {
                   1504:                        --obj->refcount;
                   1505:                        if (obj->refcount == 0)
                   1506:                                _rtld_unload_object(&mask, obj, true);
                   1507:                }
                   1508:        }
                   1509:
                   1510:        _rtld_exclusive_exit(&mask);
                   1511: }
                   1512:
1.1       cgd      1513: /*
                   1514:  * Error reporting function.  Use it like printf.  If formats the message
                   1515:  * into a buffer, and sets things up so that the next call to dlerror()
                   1516:  * will return the message.
                   1517:  */
                   1518: void
1.15      christos 1519: _rtld_error(const char *fmt,...)
1.1       cgd      1520: {
1.15      christos 1521:        static char     buf[512];
                   1522:        va_list         ap;
1.49      wiz      1523:
1.15      christos 1524:        va_start(ap, fmt);
                   1525:        xvsnprintf(buf, sizeof buf, fmt, ap);
                   1526:        error_message = buf;
                   1527:        va_end(ap);
1.1       cgd      1528: }
1.14      pk       1529:
1.1       cgd      1530: void
1.98      skrll    1531: _rtld_debug_state(void)
1.1       cgd      1532: {
1.175     skrll    1533: #if defined(__hppa__)
                   1534:        __asm volatile("nop" ::: "memory");
                   1535: #endif
1.94      simonb   1536:
1.157     joerg    1537:        /* Prevent optimizer from removing calls to this function */
                   1538:        __insn_barrier();
1.1       cgd      1539: }
                   1540:
                   1541: void
1.98      skrll    1542: _rtld_linkmap_add(Obj_Entry *obj)
1.1       cgd      1543: {
1.15      christos 1544:        struct link_map *l = &obj->linkmap;
                   1545:        struct link_map *prev;
1.1       cgd      1546:
1.15      christos 1547:        obj->linkmap.l_name = obj->path;
1.68      mycroft  1548:        obj->linkmap.l_addr = obj->relocbase;
1.15      christos 1549:        obj->linkmap.l_ld = obj->dynamic;
1.6       mhitch   1550: #ifdef __mips__
1.72      mycroft  1551:        /* XXX This field is not standard and will be removed eventually. */
1.15      christos 1552:        obj->linkmap.l_offs = obj->relocbase;
1.6       mhitch   1553: #endif
1.1       cgd      1554:
1.15      christos 1555:        if (_rtld_debug.r_map == NULL) {
                   1556:                _rtld_debug.r_map = l;
                   1557:                return;
                   1558:        }
1.109     skrll    1559:
                   1560:        /*
                   1561:         * Scan to the end of the list, but not past the entry for the
                   1562:         * dynamic linker, which we want to keep at the very end.
                   1563:         */
                   1564:        for (prev = _rtld_debug.r_map;
                   1565:            prev->l_next != NULL && prev->l_next != &_rtld_objself.linkmap;
                   1566:            prev = prev->l_next);
                   1567:
1.15      christos 1568:        l->l_prev = prev;
1.109     skrll    1569:        l->l_next = prev->l_next;
                   1570:        if (l->l_next != NULL)
                   1571:                l->l_next->l_prev = l;
1.15      christos 1572:        prev->l_next = l;
1.1       cgd      1573: }
                   1574:
                   1575: void
1.98      skrll    1576: _rtld_linkmap_delete(Obj_Entry *obj)
1.1       cgd      1577: {
1.15      christos 1578:        struct link_map *l = &obj->linkmap;
1.1       cgd      1579:
1.15      christos 1580:        if (l->l_prev == NULL) {
                   1581:                if ((_rtld_debug.r_map = l->l_next) != NULL)
                   1582:                        l->l_next->l_prev = NULL;
                   1583:                return;
                   1584:        }
                   1585:        if ((l->l_prev->l_next = l->l_next) != NULL)
                   1586:                l->l_next->l_prev = l->l_prev;
1.25      mycroft  1587: }
                   1588:
                   1589: static Obj_Entry *
                   1590: _rtld_obj_from_addr(const void *addr)
                   1591: {
                   1592:        Obj_Entry *obj;
1.165     skrll    1593:
1.25      mycroft  1594:        for (obj = _rtld_objlist;  obj != NULL;  obj = obj->next) {
                   1595:                if (addr < (void *) obj->mapbase)
                   1596:                        continue;
1.67      mycroft  1597:                if (addr < (void *) (obj->mapbase + obj->mapsize))
1.25      mycroft  1598:                        return obj;
                   1599:        }
                   1600:        return NULL;
                   1601: }
                   1602:
                   1603: static void
1.117     ad       1604: _rtld_objlist_clear(Objlist *list)
                   1605: {
                   1606:        while (!SIMPLEQ_EMPTY(list)) {
                   1607:                Objlist_Entry* elm = SIMPLEQ_FIRST(list);
                   1608:                SIMPLEQ_REMOVE_HEAD(list, link);
                   1609:                xfree(elm);
                   1610:        }
                   1611: }
                   1612:
                   1613: static void
1.98      skrll    1614: _rtld_objlist_remove(Objlist *list, Obj_Entry *obj)
1.25      mycroft  1615: {
                   1616:        Objlist_Entry *elm;
1.165     skrll    1617:
1.25      mycroft  1618:        if ((elm = _rtld_objlist_find(list, obj)) != NULL) {
1.50      lukem    1619:                SIMPLEQ_REMOVE(list, elm, Struct_Objlist_Entry, link);
1.116     ad       1620:                xfree(elm);
1.25      mycroft  1621:        }
1.1       cgd      1622: }
1.141     joerg    1623:
                   1624: #define        RTLD_EXCLUSIVE_MASK     0x80000000U
                   1625: static volatile unsigned int _rtld_mutex;
                   1626: static volatile unsigned int _rtld_waiter_exclusive;
                   1627: static volatile unsigned int _rtld_waiter_shared;
                   1628:
                   1629: void
                   1630: _rtld_shared_enter(void)
                   1631: {
                   1632:        unsigned int cur;
                   1633:        lwpid_t waiter, self = 0;
                   1634:
                   1635:        membar_enter();
                   1636:
                   1637:        for (;;) {
                   1638:                cur = _rtld_mutex;
                   1639:                /*
                   1640:                 * First check if we are currently not exclusively locked.
                   1641:                 */
                   1642:                if ((cur & RTLD_EXCLUSIVE_MASK) == 0) {
                   1643:                        /* Yes, so increment use counter */
                   1644:                        if (atomic_cas_uint(&_rtld_mutex, cur, cur + 1) != cur)
                   1645:                                continue;
1.177     yamt     1646:                        membar_enter();
1.141     joerg    1647:                        return;
                   1648:                }
                   1649:                /*
                   1650:                 * Someone has an exclusive lock.  Puts us on the waiter list.
                   1651:                 */
                   1652:                if (!self)
                   1653:                        self = _lwp_self();
                   1654:                if (cur == (self | RTLD_EXCLUSIVE_MASK)) {
                   1655:                        if (_rtld_mutex_may_recurse)
                   1656:                                return;
                   1657:                        _rtld_error("dead lock detected");
                   1658:                        _rtld_die();
                   1659:                }
                   1660:                waiter = atomic_swap_uint(&_rtld_waiter_shared, self);
                   1661:                /*
                   1662:                 * Check for race against _rtld_exclusive_exit before sleeping.
                   1663:                 */
1.177     yamt     1664:                membar_sync();
1.141     joerg    1665:                if ((_rtld_mutex & RTLD_EXCLUSIVE_MASK) ||
                   1666:                    _rtld_waiter_exclusive)
1.172     joerg    1667:                        _lwp_park(CLOCK_REALTIME, 0, NULL, 0,
                   1668:                            __UNVOLATILE(&_rtld_mutex), NULL);
1.141     joerg    1669:                /* Try to remove us from the waiter list. */
                   1670:                atomic_cas_uint(&_rtld_waiter_shared, self, 0);
                   1671:                if (waiter)
                   1672:                        _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
                   1673:        }
                   1674: }
                   1675:
                   1676: void
                   1677: _rtld_shared_exit(void)
                   1678: {
                   1679:        lwpid_t waiter;
                   1680:
                   1681:        /*
                   1682:         * Shared lock taken after an exclusive lock.
                   1683:         * Just assume this is a partial recursion.
                   1684:         */
                   1685:        if (_rtld_mutex & RTLD_EXCLUSIVE_MASK)
                   1686:                return;
                   1687:
                   1688:        /*
                   1689:         * Wakeup LWPs waiting for an exclusive lock if this is the last
                   1690:         * LWP on the shared lock.
                   1691:         */
1.177     yamt     1692:        membar_exit();
1.141     joerg    1693:        if (atomic_dec_uint_nv(&_rtld_mutex))
                   1694:                return;
1.177     yamt     1695:        membar_sync();
1.141     joerg    1696:        if ((waiter = _rtld_waiter_exclusive) != 0)
                   1697:                _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
                   1698: }
                   1699:
                   1700: void
1.148     joerg    1701: _rtld_exclusive_enter(sigset_t *mask)
1.141     joerg    1702: {
                   1703:        lwpid_t waiter, self = _lwp_self();
                   1704:        unsigned int locked_value = (unsigned int)self | RTLD_EXCLUSIVE_MASK;
                   1705:        unsigned int cur;
1.148     joerg    1706:        sigset_t blockmask;
                   1707:
                   1708:        sigfillset(&blockmask);
1.153     christos 1709:        sigdelset(&blockmask, SIGTRAP); /* Allow the debugger */
1.148     joerg    1710:        sigprocmask(SIG_BLOCK, &blockmask, mask);
1.141     joerg    1711:
                   1712:        for (;;) {
1.177     yamt     1713:                if (atomic_cas_uint(&_rtld_mutex, 0, locked_value) == 0) {
                   1714:                        membar_enter();
1.141     joerg    1715:                        break;
1.177     yamt     1716:                }
1.141     joerg    1717:                waiter = atomic_swap_uint(&_rtld_waiter_exclusive, self);
1.177     yamt     1718:                membar_sync();
1.141     joerg    1719:                cur = _rtld_mutex;
                   1720:                if (cur == locked_value) {
                   1721:                        _rtld_error("dead lock detected");
                   1722:                        _rtld_die();
                   1723:                }
                   1724:                if (cur)
1.172     joerg    1725:                        _lwp_park(CLOCK_REALTIME, 0, NULL, 0,
                   1726:                            __UNVOLATILE(&_rtld_mutex), NULL);
1.141     joerg    1727:                atomic_cas_uint(&_rtld_waiter_exclusive, self, 0);
                   1728:                if (waiter)
                   1729:                        _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
                   1730:        }
                   1731: }
                   1732:
                   1733: void
1.148     joerg    1734: _rtld_exclusive_exit(sigset_t *mask)
1.141     joerg    1735: {
                   1736:        lwpid_t waiter;
                   1737:
1.177     yamt     1738:        membar_exit();
1.141     joerg    1739:        _rtld_mutex = 0;
1.177     yamt     1740:        membar_sync();
1.141     joerg    1741:        if ((waiter = _rtld_waiter_exclusive) != 0)
                   1742:                _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
                   1743:
                   1744:        if ((waiter = _rtld_waiter_shared) != 0)
                   1745:                _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
                   1746:
1.148     joerg    1747:        sigprocmask(SIG_SETMASK, mask, NULL);
1.141     joerg    1748: }
1.190.2.4! pgoyette 1749:
        !          1750: int
        !          1751: _rtld_relro(const Obj_Entry *obj, bool wantmain)
        !          1752: {
        !          1753: #ifdef GNU_RELRO
        !          1754:        if (obj->relro_size == 0)
        !          1755:                return 0;
        !          1756:        if (wantmain != (obj ==_rtld_objmain))
        !          1757:                return 0;
        !          1758:
        !          1759:        dbg(("RELRO %s %p %lx\n", obj->path, obj->relro_page, obj->relro_size));
        !          1760:        if (mprotect(obj->relro_page, obj->relro_size, PROT_READ) == -1) {
        !          1761:                _rtld_error("%s: Cannot enforce relro " "protection: %s",
        !          1762:                    obj->path, xstrerror(errno));
        !          1763:                return -1;
        !          1764:        }
        !          1765: #endif
        !          1766:        return 0;
        !          1767: }

CVSweb <webmaster@jp.NetBSD.org>