LCOV - code coverage report
Current view: directory - xpcom/glue/standalone - nsGlueLinkingDlopen.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 69 60 87.0 %
Date: 2012-06-02 Functions: 6 6 100.0 %

       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             552 : AppendDependentLib(void *libHandle)
     151                 : {
     152             552 :     DependentLib *d = new DependentLib;
     153             552 :     if (!d)
     154               0 :         return;
     155                 : 
     156             552 :     d->next = sTop;
     157             552 :     d->libHandle = libHandle;
     158                 : 
     159             552 :     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             506 : preload(const char *file)
     179                 : {
     180                 :     union {
     181                 :         char buf[bufsize];
     182                 :         Elf_Ehdr ehdr;
     183                 :     } elf;
     184             506 :     int fd = open(file, O_RDONLY);
     185             506 :     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            1518 :     if ((read(fd, elf.buf, bufsize) <= 0) ||
     192             506 :         (memcmp(elf.buf, ELFMAG, 4)) ||
     193             506 :         (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             506 :     Elf_Phdr *phdr = (Elf_Phdr *)&elf.buf[elf.ehdr.e_phoff];
     204             506 :     Elf_Off end = 0;
     205            2898 :     for (int phnum = elf.ehdr.e_phnum; phnum; phdr++, phnum--)
     206            2392 :         if ((phdr->p_type == PT_LOAD) &&
     207                 :             (end < phdr->p_offset + phdr->p_filesz))
     208            1150 :             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             506 :     if (end > 0) {
     212             506 :         readahead(fd, 0, end);
     213                 :     }
     214             506 :     close(fd);
     215                 : }
     216                 : #endif
     217                 : 
     218                 : static void
     219             506 : ReadDependentCB(const char *aDependentLib, bool do_preload)
     220                 : {
     221                 : #if defined(LINUX) && !defined(ANDROID)
     222             506 :     if (do_preload)
     223             506 :         preload(aDependentLib);
     224                 : #endif
     225             506 :     void *libHandle = dlopen(aDependentLib, RTLD_GLOBAL | RTLD_LAZY);
     226             506 :     if (!libHandle)
     227               0 :         return;
     228                 : 
     229             506 :     AppendDependentLib(libHandle);
     230                 : }
     231                 : 
     232                 : nsresult
     233              46 : XPCOMGlueLoad(const char *xpcomFile, GetFrozenFunctionsFunc *func)
     234                 : {
     235                 :     char xpcomDir[MAXPATHLEN];
     236              46 :     if (realpath(xpcomFile, xpcomDir)) {
     237              46 :         char *lastSlash = strrchr(xpcomDir, '/');
     238              46 :         if (lastSlash) {
     239              46 :             *lastSlash = '\0';
     240                 : 
     241              46 :             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              46 :             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              46 :     void *libHandle = nsnull;
     268                 : 
     269              46 :     if (xpcomFile[0] != '.' || xpcomFile[1] != '\0') {
     270              46 :         libHandle = dlopen(xpcomFile, RTLD_GLOBAL | RTLD_LAZY);
     271              46 :         if (libHandle) {
     272              46 :             AppendDependentLib(libHandle);
     273                 :         } else {
     274                 :             fprintf(stderr, "XPCOMGlueLoad error for file %s:\n%s\n", xpcomFile,
     275               0 :                     dlerror());
     276                 :         }
     277                 :     }
     278                 : 
     279                 :     GetFrozenFunctionsFunc sym =
     280                 :         (GetFrozenFunctionsFunc) dlsym(libHandle,
     281              46 :                                        LEADING_UNDERSCORE "NS_GetFrozenFunctions");
     282                 : 
     283              46 :     if (!sym) { // No symbol found.
     284               0 :         XPCOMGlueUnload();
     285               0 :         return NS_ERROR_NOT_AVAILABLE;
     286                 :     }
     287                 : 
     288              46 :     *func = sym;
     289                 : 
     290              46 :     return NS_OK;
     291                 : }
     292                 : 
     293                 : void
     294              23 : XPCOMGlueUnload()
     295                 : {
     296             322 :     while (sTop) {
     297             276 :         dlclose(sTop->libHandle);
     298                 : 
     299             276 :         DependentLib *temp = sTop;
     300             276 :         sTop = sTop->next;
     301                 : 
     302             276 :         delete temp;
     303                 :     }
     304                 : 
     305              23 :     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              23 :         dlclose(sXULLibHandle);
     315              23 :         sXULLibHandle = nsnull;
     316                 :     }
     317              23 : }
     318                 : 
     319                 : nsresult
     320              46 : 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              46 :     nsresult rv = NS_OK;
     326             322 :     while (symbols->functionName) {
     327                 :         char buffer[512];
     328                 :         snprintf(buffer, sizeof(buffer),
     329             230 :                  LEADING_UNDERSCORE "%s", symbols->functionName);
     330                 : 
     331             230 :         *symbols->function = (NSFuncPtr) dlsym(sXULLibHandle, buffer);
     332             230 :         if (!*symbols->function)
     333               0 :             rv = NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
     334                 : 
     335             230 :         ++symbols;
     336                 :     }
     337              46 :     return rv;
     338                 : }

Generated by: LCOV version 1.7