LCOV - app.info - xpcom/glue/standalone/nsGlueLinkingDlopen.cpp

LCOV - code coverage report
| Current view: | directory - xpcom/glue/standalone - nsGlueLinkingDlopen.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 69 | 15 | 21.7 %
| Date: | 2012-04-07 | Functions: | 6 | 2 | 33.3 %

           1                 : /* -*- Mode: C++; tab-width: 6; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is Mozilla XPCOM.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Benjamin Smedberg <benjamin@smedbergs.us>
          19                 :  *
          20                 :  * Portions created by the Initial Developer are Copyright (C) 2005
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   Mike Hommey <mh@glandium.org>
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : #include "nsGlueLinking.h"
          41                 : #include "nsXPCOMGlue.h"
          42                 : #include "nscore.h"
          43                 :
          44                 : #if defined(LINUX) && !defined(ANDROID)
          45                 : #define _GNU_SOURCE
          46                 : #include <fcntl.h>
          47                 : #include <unistd.h>
          48                 : #include <elf.h>
          49                 : #include <limits.h>
          50                 : #endif
          51                 :
          52                 : #include <errno.h>
          53                 : #include <dlfcn.h>
          54                 : #include <stdlib.h>
          55                 : #include <string.h>
          56                 : #include <stdio.h>
          57                 :
          58                 : #if defined(SUNOS4) || defined(NEXTSTEP) || \
          59                 :     (defined(OPENBSD) || defined(NETBSD)) && !defined(__ELF__)
          60                 : #define LEADING_UNDERSCORE "_"
          61                 : #else
          62                 : #define LEADING_UNDERSCORE
          63                 : #endif
          64                 :
          65                 : #if defined(MOZ_LINKER) && !defined(ANDROID)
          66                 : extern "C" {
          67                 : NS_HIDDEN __typeof(dlopen) __wrap_dlopen;
          68                 : NS_HIDDEN __typeof(dlsym) __wrap_dlsym;
          69                 : NS_HIDDEN __typeof(dlclose) __wrap_dlclose;
          70                 : }
          71                 :
          72                 : #define dlopen __wrap_dlopen
          73                 : #define dlsym __wrap_dlsym
          74                 : #define dlclose __wrap_dlclose
          75                 : #endif
          76                 :
          77                 : #ifdef NS_TRACE_MALLOC
          78                 : extern "C" {
          79                 : NS_EXPORT_(__ptr_t) __libc_malloc(size_t);
          80                 : NS_EXPORT_(__ptr_t) __libc_calloc(size_t, size_t);
          81                 : NS_EXPORT_(__ptr_t) __libc_realloc(__ptr_t, size_t);
          82                 : NS_EXPORT_(void)    __libc_free(__ptr_t);
          83                 : NS_EXPORT_(__ptr_t) __libc_memalign(size_t, size_t);
          84                 : NS_EXPORT_(__ptr_t) __libc_valloc(size_t);
          85                 : }
          86                 :
          87                 : static __ptr_t (*_malloc)(size_t) = __libc_malloc;
          88                 : static __ptr_t (*_calloc)(size_t, size_t) = __libc_calloc;
          89                 : static __ptr_t (*_realloc)(__ptr_t, size_t) = __libc_realloc;
          90                 : static void (*_free)(__ptr_t) = __libc_free;
          91                 : static __ptr_t (*_memalign)(size_t, size_t) = __libc_memalign;
          92                 : static __ptr_t (*_valloc)(size_t) = __libc_valloc;
          93                 :
          94                 : NS_EXPORT_(__ptr_t) malloc(size_t size)
          95                 : {
          96                 :     return _malloc(size);
          97                 : }
          98                 :
          99                 : NS_EXPORT_(__ptr_t) calloc(size_t nmemb, size_t size)
         100                 : {
         101                 :     return _calloc(nmemb, size);
         102                 : }
         103                 :
         104                 : NS_EXPORT_(__ptr_t) realloc(__ptr_t ptr, size_t size)
         105                 : {
         106                 :     return _realloc(ptr, size);
         107                 : }
         108                 :
         109                 : NS_EXPORT_(void) free(__ptr_t ptr)
         110                 : {
         111                 :     _free(ptr);
         112                 : }
         113                 :
         114                 : NS_EXPORT_(void) cfree(__ptr_t ptr)
         115                 : {
         116                 :     _free(ptr);
         117                 : }
         118                 :
         119                 : NS_EXPORT_(__ptr_t) memalign(size_t boundary, size_t size)
         120                 : {
         121                 :     return _memalign(boundary, size);
         122                 : }
         123                 :
         124                 : NS_EXPORT_(int)
         125                 : posix_memalign(void **memptr, size_t alignment, size_t size)
         126                 : {
         127                 :     __ptr_t ptr = _memalign(alignment, size);
         128                 :     if (!ptr)
         129                 :         return ENOMEM;
         130                 :     *memptr = ptr;
         131                 :     return 0;
         132                 : }
         133                 :
         134                 : NS_EXPORT_(__ptr_t) valloc(size_t size)
         135                 : {
         136                 :     return _valloc(size);
         137                 : }
         138                 : #endif /* NS_TRACE_MALLOC */
         139                 :
         140                 : struct DependentLib
         141                 : {
         142                 :     void         *libHandle;
         143                 :     DependentLib *next;
         144                 : };
         145                 :
         146                 : static DependentLib *sTop;
         147                 : static void* sXULLibHandle;
         148                 :
         149                 : static void
         150               0 : AppendDependentLib(void *libHandle)
         151                 : {
         152               0 :     DependentLib *d = new DependentLib;
         153               0 :     if (!d)
         154               0 :         return;
         155                 :
         156               0 :     d->next = sTop;
         157               0 :     d->libHandle = libHandle;
         158                 :
         159               0 :     sTop = d;
         160                 : }
         161                 :
         162                 : #if defined(LINUX) && !defined(ANDROID)
         163                 : static const unsigned int bufsize = 4096;
         164                 :
         165                 : #ifdef HAVE_64BIT_OS
         166                 : typedef Elf64_Ehdr Elf_Ehdr;
         167                 : typedef Elf64_Phdr Elf_Phdr;
         168                 : static const unsigned char ELFCLASS = ELFCLASS64;
         169                 : typedef Elf64_Off Elf_Off;
         170                 : #else
         171                 : typedef Elf32_Ehdr Elf_Ehdr;
         172                 : typedef Elf32_Phdr Elf_Phdr;
         173                 : static const unsigned char ELFCLASS = ELFCLASS32;
         174                 : typedef Elf32_Off Elf_Off;
         175                 : #endif
         176                 :
         177                 : static void
         178               0 : preload(const char *file)
         179                 : {
         180                 :     union {
         181                 :         char buf[bufsize];
         182                 :         Elf_Ehdr ehdr;
         183                 :     } elf;
         184               0 :     int fd = open(file, O_RDONLY);
         185               0 :     if (fd < 0)
         186               0 :         return;
         187                 :     // Read ELF header (ehdr) and program header table (phdr).
         188                 :     // We check that the ELF magic is found, that the ELF class matches
         189                 :     // our own, and that the program header table as defined in the ELF
         190                 :     // headers fits in the buffer we read.
         191               0 :     if ((read(fd, elf.buf, bufsize) <= 0) ||
         192               0 :         (memcmp(elf.buf, ELFMAG, 4)) ||
         193               0 :         (elf.ehdr.e_ident[EI_CLASS] != ELFCLASS) ||
         194                 :         (elf.ehdr.e_phoff + elf.ehdr.e_phentsize * elf.ehdr.e_phnum >= bufsize)) {
         195               0 :         close(fd);
         196               0 :         return;
         197                 :     }
         198                 :     // The program header table contains segment definitions. One such
         199                 :     // segment type is PT_LOAD, which describes how the dynamic loader
         200                 :     // is going to map the file in memory. We use that information to
         201                 :     // find the biggest offset from the library that will be mapped in
         202                 :     // memory.
         203               0 :     Elf_Phdr *phdr = (Elf_Phdr *)&elf.buf[elf.ehdr.e_phoff];
         204               0 :     Elf_Off end = 0;
         205               0 :     for (int phnum = elf.ehdr.e_phnum; phnum; phdr++, phnum--)
         206               0 :         if ((phdr->p_type == PT_LOAD) &&
         207                 :             (end < phdr->p_offset + phdr->p_filesz))
         208               0 :             end = phdr->p_offset + phdr->p_filesz;
         209                 :     // Let the kernel read ahead what the dynamic loader is going to
         210                 :     // map in memory soon after.
         211               0 :     if (end > 0) {
         212               0 :         readahead(fd, 0, end);
         213                 :     }
         214               0 :     close(fd);
         215                 : }
         216                 : #endif
         217                 :
         218                 : static void
         219               0 : ReadDependentCB(const char *aDependentLib, bool do_preload)
         220                 : {
         221                 : #if defined(LINUX) && !defined(ANDROID)
         222               0 :     if (do_preload)
         223               0 :         preload(aDependentLib);
         224                 : #endif
         225               0 :     void *libHandle = dlopen(aDependentLib, RTLD_GLOBAL | RTLD_LAZY);
         226               0 :     if (!libHandle)
         227               0 :         return;
         228                 :
         229               0 :     AppendDependentLib(libHandle);
         230                 : }
         231                 :
         232                 : nsresult
         233               2 : XPCOMGlueLoad(const char *xpcomFile, GetFrozenFunctionsFunc *func)
         234                 : {
         235                 :     char xpcomDir[MAXPATHLEN];
         236               2 :     if (realpath(xpcomFile, xpcomDir)) {
         237               0 :         char *lastSlash = strrchr(xpcomDir, '/');
         238               0 :         if (lastSlash) {
         239               0 :             *lastSlash = '\0';
         240                 :
         241               0 :             XPCOMGlueLoadDependentLibs(xpcomDir, ReadDependentCB);
         242                 :
         243                 : #ifdef __GLIBC__
         244                 :             // XUL_DLL is already loaded by XPCOMGlueLoadDependentLibs, so
         245                 :             // dlopening without the full path will return that one.
         246               0 :             sXULLibHandle = dlopen(XUL_DLL, RTLD_GLOBAL | RTLD_LAZY);
         247                 : #else
         248                 :             snprintf(lastSlash, MAXPATHLEN - strlen(xpcomDir), "/" XUL_DLL);
         249                 :
         250                 :             sXULLibHandle = dlopen(xpcomDir, RTLD_GLOBAL | RTLD_LAZY);
         251                 : #endif
         252                 :
         253                 : #ifdef NS_TRACE_MALLOC
         254                 :             _malloc = (__ptr_t(*)(size_t)) dlsym(sXULLibHandle, "malloc");
         255                 :             _calloc = (__ptr_t(*)(size_t, size_t)) dlsym(sXULLibHandle, "calloc");
         256                 :             _realloc = (__ptr_t(*)(__ptr_t, size_t)) dlsym(sXULLibHandle, "realloc");
         257                 :             _free = (void(*)(__ptr_t)) dlsym(sXULLibHandle, "free");
         258                 :             _memalign = (__ptr_t(*)(size_t, size_t)) dlsym(sXULLibHandle, "memalign");
         259                 :             _valloc = (__ptr_t(*)(size_t)) dlsym(sXULLibHandle, "valloc");
         260                 : #endif
         261                 :         }
         262                 :     }
         263                 :
         264                 :     // RTLD_DEFAULT is not defined in non-GNU toolchains, and it is
         265                 :     // (void*) 0 in any case.
         266                 :
         267               2 :     void *libHandle = nsnull;
         268                 :
         269               2 :     if (xpcomFile[0] != '.' || xpcomFile[1] != '\0') {
         270               2 :         libHandle = dlopen(xpcomFile, RTLD_GLOBAL | RTLD_LAZY);
         271               2 :         if (libHandle) {
         272               0 :             AppendDependentLib(libHandle);
         273                 :         } else {
         274                 :             fprintf(stderr, "XPCOMGlueLoad error for file %s:\n%s\n", xpcomFile,
         275               2 :                     dlerror());
         276                 :         }
         277                 :     }
         278                 :
         279                 :     GetFrozenFunctionsFunc sym =
         280                 :         (GetFrozenFunctionsFunc) dlsym(libHandle,
         281               2 :                                        LEADING_UNDERSCORE "NS_GetFrozenFunctions");
         282                 :
         283               2 :     if (!sym) { // No symbol found.
         284               2 :         XPCOMGlueUnload();
         285               2 :         return NS_ERROR_NOT_AVAILABLE;
         286                 :     }
         287                 :
         288               0 :     *func = sym;
         289                 :
         290               0 :     return NS_OK;
         291                 : }
         292                 :
         293                 : void
         294               2 : XPCOMGlueUnload()
         295                 : {
         296               4 :     while (sTop) {
         297               0 :         dlclose(sTop->libHandle);
         298                 :
         299               0 :         DependentLib *temp = sTop;
         300               0 :         sTop = sTop->next;
         301                 :
         302               0 :         delete temp;
         303                 :     }
         304                 :
         305               2 :     if (sXULLibHandle) {
         306                 : #ifdef NS_TRACE_MALLOC
         307                 :         _malloc = __libc_malloc;
         308                 :         _calloc = __libc_calloc;
         309                 :         _realloc = __libc_realloc;
         310                 :         _free = __libc_free;
         311                 :         _memalign = __libc_memalign;
         312                 :         _valloc = __libc_valloc;
         313                 : #endif
         314               0 :         dlclose(sXULLibHandle);
         315               0 :         sXULLibHandle = nsnull;
         316                 :     }
         317               2 : }
         318                 :
         319                 : nsresult
         320               0 : XPCOMGlueLoadXULFunctions(const nsDynamicFunctionLoad *symbols)
         321                 : {
         322                 :     // We don't null-check sXULLibHandle because this might work even
         323                 :     // if it is null (same as RTLD_DEFAULT)
         324                 :
         325               0 :     nsresult rv = NS_OK;
         326               0 :     while (symbols->functionName) {
         327                 :         char buffer[512];
         328                 :         snprintf(buffer, sizeof(buffer),
         329               0 :                  LEADING_UNDERSCORE "%s", symbols->functionName);
         330                 :
         331               0 :         *symbols->function = (NSFuncPtr) dlsym(sXULLibHandle, buffer);
         332               0 :         if (!*symbols->function)
         333               0 :             rv = NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
         334                 :
         335               0 :         ++symbols;
         336                 :     }
         337               0 :     return rv;
         338                 : }

Generated by: LCOV version 1.7