LCOV - code coverage report
Current view: top level - jvmfwk/plugins/sunmajor/pluginlib - sunjavaplugin.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 170 253 67.2 %
Date: 2014-11-03 Functions: 11 12 91.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #ifdef WNT
      22             : # include <stdio.h>
      23             : # include <sys/stat.h>
      24             : # include <windows.h>
      25             : #endif
      26             : 
      27             : #ifdef ANDROID
      28             : # include <dlfcn.h>
      29             : #endif
      30             : 
      31             : #if OSL_DEBUG_LEVEL > 0
      32             : #include <stdio.h>
      33             : #endif
      34             : #include <string.h>
      35             : 
      36             : #include "boost/scoped_array.hpp"
      37             : #include "config_options.h"
      38             : #include "osl/diagnose.h"
      39             : #include "rtl/ustring.hxx"
      40             : #include "rtl/ustrbuf.hxx"
      41             : #include "osl/module.hxx"
      42             : #include "osl/mutex.hxx"
      43             : #include "osl/process.h"
      44             : #include "osl/thread.hxx"
      45             : #include "osl/file.hxx"
      46             : #include "rtl/instance.hxx"
      47             : #include "osl/getglobalmutex.hxx"
      48             : #include <setjmp.h>
      49             : #include <signal.h>
      50             : #include <stack>
      51             : 
      52             : #include "jni.h"
      53             : #include "rtl/byteseq.hxx"
      54             : #include "vendorplugin.hxx"
      55             : #include "util.hxx"
      56             : #include "sunversion.hxx"
      57             : #include "vendorlist.hxx"
      58             : #include "diagnostics.h"
      59             : 
      60             : #ifdef ANDROID
      61             : #include <osl/detail/android-bootstrap.h>
      62             : #else
      63             : #if !ENABLE_RUNTIME_OPTIMIZATIONS
      64             : #define FORCE_INTERPRETED 1
      65             : #elif defined HAVE_VALGRIND_HEADERS
      66             : #include <valgrind/valgrind.h>
      67             : #define FORCE_INTERPRETED RUNNING_ON_VALGRIND
      68             : #else
      69             : #define FORCE_INTERPRETED 0
      70             : #endif
      71             : #endif
      72             : 
      73             : #if defined LINUX && defined X86
      74             : #include <sys/resource.h>
      75             : #endif
      76             : 
      77             : using namespace osl;
      78             : using namespace std;
      79             : using namespace jfw_plugin;
      80             : 
      81             : 
      82             : namespace {
      83             : 
      84             : struct PluginMutex: public ::rtl::Static<osl::Mutex, PluginMutex> {};
      85             : 
      86             : #if defined UNX
      87           4 : OString getPluginJarPath(
      88             :     const OUString & sVendor,
      89             :     const OUString& sLocation,
      90             :     const OUString& sVersion)
      91             : {
      92           4 :     OString ret;
      93           8 :     OUString sName1("javaplugin.jar");
      94           8 :     OUString sName2("plugin.jar");
      95           8 :     OUString sPath;
      96           4 :     if ( sVendor == "Sun Microsystems Inc." )
      97             :     {
      98           0 :         SunVersion ver142("1.4.2-ea");
      99           0 :         SunVersion ver150("1.5.0-ea");
     100           0 :         SunVersion ver(sVersion);
     101             :         OSL_ASSERT(ver142 && ver150 && ver);
     102             : 
     103           0 :         OUString sName;
     104           0 :         if (ver < ver142)
     105             :         {
     106           0 :             sName = sName1;
     107             :         }
     108           0 :         else if (ver < ver150)
     109             :         {//this will cause ea, beta etc. to have plugin.jar in path.
     110             :             //but this does not harm. 1.5.0-beta < 1.5.0
     111           0 :             sName = sName2;
     112             :         }
     113           0 :         if (!sName.isEmpty())
     114             :         {
     115           0 :             sName = sLocation + "/lib/" + sName;
     116           0 :             OSL_VERIFY(
     117             :                 osl_getSystemPathFromFileURL(sName.pData, & sPath.pData)
     118             :                 == osl_File_E_None);
     119           0 :         }
     120             :     }
     121             :     else
     122             :     {
     123           4 :         char sep[] =  {SAL_PATHSEPARATOR, 0};
     124           4 :         OUString sName(sLocation + "/lib/" + sName1);
     125           8 :         OUString sPath1;
     126           8 :         OUString sPath2;
     127           4 :         if (osl_getSystemPathFromFileURL(sName.pData, & sPath1.pData)
     128             :             == osl_File_E_None)
     129             :         {
     130           4 :             sName = sLocation + "/lib/" + sName2;
     131           4 :             if (osl_getSystemPathFromFileURL(sName.pData, & sPath2.pData)
     132             :                 == osl_File_E_None)
     133             :             {
     134           4 :                 sPath = sPath1 + OUString::createFromAscii(sep) + sPath2;
     135             :             }
     136             :         }
     137           4 :         OSL_ASSERT(!sPath.isEmpty());
     138             :     }
     139           4 :     ret = OUStringToOString(sPath, osl_getThreadTextEncoding());
     140             : 
     141           8 :     return ret;
     142             : }
     143             : #endif // UNX
     144             : 
     145             : 
     146         116 : JavaInfo* createJavaInfo(const rtl::Reference<VendorBase> & info)
     147             : {
     148         116 :     JavaInfo* pInfo = (JavaInfo*) rtl_allocateMemory(sizeof(JavaInfo));
     149         116 :     if (pInfo == NULL)
     150           0 :         return NULL;
     151         116 :     OUString sVendor = info->getVendor();
     152         116 :     pInfo->sVendor = sVendor.pData;
     153         116 :     rtl_uString_acquire(sVendor.pData);
     154         232 :     OUString sHome = info->getHome();
     155         116 :     pInfo->sLocation = sHome.pData;
     156         116 :     rtl_uString_acquire(pInfo->sLocation);
     157         232 :     OUString sVersion = info->getVersion();
     158         116 :     pInfo->sVersion = sVersion.pData;
     159         116 :     rtl_uString_acquire(pInfo->sVersion);
     160         116 :     pInfo->nFeatures = info->supportsAccessibility() ? 1 : 0;
     161         116 :     pInfo->nRequirements = info->needsRestart() ? JFW_REQUIRE_NEEDRESTART : 0;
     162         232 :     OUStringBuffer buf(1024);
     163         116 :     buf.append(info->getRuntimeLibrary());
     164         116 :     if (!info->getLibraryPath().isEmpty())
     165             :     {
     166         116 :         buf.appendAscii("\n");
     167         116 :         buf.append(info->getLibraryPath());
     168         116 :         buf.appendAscii("\n");
     169             :     }
     170             : 
     171         232 :     OUString sVendorData = buf.makeStringAndClear();
     172             :     rtl::ByteSequence byteSeq( (sal_Int8*) sVendorData.pData->buffer,
     173         232 :                                sVendorData.getLength() * sizeof(sal_Unicode));
     174         116 :     pInfo->arVendorData = byteSeq.get();
     175         116 :     rtl_byte_sequence_acquire(pInfo->arVendorData);
     176             : 
     177         232 :     return pInfo;
     178             : }
     179             : 
     180         116 : OUString getRuntimeLib(const rtl::ByteSequence & data)
     181             : {
     182         116 :     const sal_Unicode* chars = (sal_Unicode*) data.getConstArray();
     183         116 :     sal_Int32 len = data.getLength();
     184         116 :     OUString sData(chars, len / 2);
     185             :     //the runtime lib is on the first line
     186         116 :     sal_Int32 index = 0;
     187         116 :     OUString aToken = sData.getToken( 0, '\n', index);
     188             : 
     189         116 :     return aToken;
     190             : }
     191             : 
     192             : jmp_buf jmp_jvm_abort;
     193             : sig_atomic_t g_bInGetJavaVM = 0;
     194             : 
     195           0 : extern "C" void JNICALL abort_handler()
     196             : {
     197             :     // If we are within JNI_CreateJavaVM then we jump back into getJavaVM
     198           0 :     if( g_bInGetJavaVM != 0 )
     199             :     {
     200           0 :         fprintf( stderr, "JavaVM: JNI_CreateJavaVM called _exit, caught by abort_handler in javavm.cxx\n");
     201           0 :         longjmp( jmp_jvm_abort, 0);
     202             :     }
     203           0 : }
     204             : 
     205             : }
     206             : 
     207          28 : javaPluginError jfw_plugin_getAllJavaInfos(
     208             :     rtl_uString *sVendor,
     209             :     rtl_uString *sMinVersion,
     210             :     rtl_uString *sMaxVersion,
     211             :     rtl_uString  * *arExcludeList,
     212             :     sal_Int32  nLenList,
     213             :     JavaInfo*** parJavaInfo,
     214             :     sal_Int32 *nLenInfoList)
     215             : {
     216             :     OSL_ASSERT(sVendor);
     217             :     OSL_ASSERT(sMinVersion);
     218             :     OSL_ASSERT(sMaxVersion);
     219             :     OSL_ASSERT(parJavaInfo);
     220             :     OSL_ASSERT(parJavaInfo);
     221             :     OSL_ASSERT(nLenInfoList);
     222          28 :     if (!sVendor || !sMinVersion || !sMaxVersion || !parJavaInfo || !nLenInfoList)
     223           0 :         return JFW_PLUGIN_E_INVALID_ARG;
     224             : 
     225             :     //nLenlist contains the number of element in arExcludeList.
     226             :     //If no exclude list is provided then nLenList must be 0
     227             :     OSL_ASSERT( ! (arExcludeList == NULL && nLenList > 0));
     228          28 :     if (arExcludeList == NULL && nLenList > 0)
     229           0 :         return JFW_PLUGIN_E_INVALID_ARG;
     230             : 
     231          28 :     OUString ouVendor(sVendor);
     232          56 :     OUString ouMinVer(sMinVersion);
     233          56 :     OUString ouMaxVer(sMaxVersion);
     234             : 
     235             :     OSL_ASSERT(!ouVendor.isEmpty());
     236          28 :     if (ouVendor.isEmpty())
     237           0 :         return JFW_PLUGIN_E_INVALID_ARG;
     238             : 
     239          28 :     JavaInfo** arInfo = NULL;
     240             : 
     241             :     //Find all JREs
     242             :     vector<rtl::Reference<VendorBase> > vecInfos =
     243          56 :         getAllJREInfos();
     244          56 :     vector<rtl::Reference<VendorBase> > vecVerifiedInfos;
     245             : 
     246             :     typedef vector<rtl::Reference<VendorBase> >::iterator it;
     247          56 :     for (it i= vecInfos.begin(); i != vecInfos.end(); ++i)
     248             :     {
     249          28 :         const rtl::Reference<VendorBase>& cur = *i;
     250             : 
     251          28 :         if (!ouVendor.equals(cur->getVendor()))
     252          14 :             continue;
     253             : 
     254          14 :         if (!ouMinVer.isEmpty())
     255             :         {
     256             :             try
     257             :             {
     258          14 :                 if (cur->compareVersions(sMinVersion) == -1)
     259           0 :                     continue;
     260             :             }
     261           0 :             catch (MalformedVersionException&)
     262             :             {
     263             :                 //The minVersion was not recognized as valid for this vendor.
     264             :                 JFW_ENSURE(
     265             :                     false,
     266             :                     "[Java framework]sunjavaplugin does not know version: "
     267             :                     + ouMinVer + " for vendor: " + cur->getVendor()
     268             :                     + " .Check minimum Version." );
     269           0 :                 return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
     270             :             }
     271             :         }
     272             : 
     273          14 :         if (!ouMaxVer.isEmpty())
     274             :         {
     275             :             try
     276             :             {
     277           0 :                 if (cur->compareVersions(sMaxVersion) == 1)
     278           0 :                     continue;
     279             :             }
     280           0 :             catch (MalformedVersionException&)
     281             :             {
     282             :                 //The maxVersion was not recognized as valid for this vendor.
     283             :                 JFW_ENSURE(
     284             :                     false,
     285             :                     "[Java framework]sunjavaplugin does not know version: "
     286             :                     + ouMaxVer + " for vendor: " + cur->getVendor()
     287             :                     + " .Check maximum Version." );
     288           0 :                 return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
     289             :             }
     290             :         }
     291             : 
     292          14 :         bool bExclude = false;
     293          14 :         for (int j = 0; j < nLenList; j++)
     294             :         {
     295           0 :             OUString sExVer(arExcludeList[j]);
     296             :             try
     297             :             {
     298           0 :                 if (cur->compareVersions(sExVer) == 0)
     299             :                 {
     300           0 :                     bExclude = true;
     301           0 :                     break;
     302             :                 }
     303             :             }
     304           0 :             catch (MalformedVersionException&)
     305             :             {
     306             :                 //The excluded version was not recognized as valid for this vendor.
     307             :                 JFW_ENSURE(
     308             :                     false,
     309             :                     "[Java framework]sunjavaplugin does not know version: "
     310             :                     + sExVer + " for vendor: " + cur->getVendor()
     311             :                     + " .Check excluded versions." );
     312           0 :                 return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
     313             :             }
     314           0 :         }
     315          14 :         if (bExclude == true)
     316           0 :             continue;
     317             : 
     318          14 :         vecVerifiedInfos.push_back(*i);
     319             :     }
     320             :     //Now vecVerifiedInfos contains all those JREs which meet the version requirements
     321             :     //Transfer them into the array that is passed out.
     322          28 :     arInfo = (JavaInfo**) rtl_allocateMemory(vecVerifiedInfos.size() * sizeof (JavaInfo*));
     323          28 :     int j = 0;
     324             :     typedef vector<rtl::Reference<VendorBase> >::const_iterator cit;
     325          42 :     for (cit ii = vecVerifiedInfos.begin(); ii != vecVerifiedInfos.end(); ++ii, ++j)
     326             :     {
     327          14 :         arInfo[j] = createJavaInfo(*ii);
     328             :     }
     329          28 :     *nLenInfoList = vecVerifiedInfos.size();
     330             : 
     331             : 
     332          28 :     *parJavaInfo = arInfo;
     333          56 :     return JFW_PLUGIN_E_NONE;
     334             : }
     335             : 
     336         204 : javaPluginError jfw_plugin_getJavaInfoByPath(
     337             :     rtl_uString *path,
     338             :     rtl_uString *sVendor,
     339             :     rtl_uString *sMinVersion,
     340             :     rtl_uString *sMaxVersion,
     341             :     rtl_uString  *  *arExcludeList,
     342             :     sal_Int32  nLenList,
     343             :     JavaInfo ** ppInfo)
     344             : {
     345         204 :     javaPluginError errorcode = JFW_PLUGIN_E_NONE;
     346             : 
     347             :     OSL_ASSERT(path);
     348             :     OSL_ASSERT(sVendor);
     349             :     OSL_ASSERT(sMinVersion);
     350             :     OSL_ASSERT(sMaxVersion);
     351         204 :     if (!path || !sVendor || !sMinVersion || !sMaxVersion || !ppInfo)
     352           0 :         return JFW_PLUGIN_E_INVALID_ARG;
     353         204 :     OUString ouPath(path);
     354             :     OSL_ASSERT(!ouPath.isEmpty());
     355         204 :     if (ouPath.isEmpty())
     356           0 :         return JFW_PLUGIN_E_INVALID_ARG;
     357             : 
     358             :     //nLenlist contains the number of element in arExcludeList.
     359             :     //If no exclude list is provided then nLenList must be 0
     360             :     OSL_ASSERT( ! (arExcludeList == NULL && nLenList > 0));
     361         204 :     if (arExcludeList == NULL && nLenList > 0)
     362           0 :         return JFW_PLUGIN_E_INVALID_ARG;
     363             : 
     364         408 :     OUString ouVendor(sVendor);
     365         408 :     OUString ouMinVer(sMinVersion);
     366         408 :     OUString ouMaxVer(sMaxVersion);
     367             : 
     368             :     OSL_ASSERT(!ouVendor.isEmpty());
     369         204 :     if (ouVendor.isEmpty())
     370           0 :         return JFW_PLUGIN_E_INVALID_ARG;
     371             : 
     372         408 :     rtl::Reference<VendorBase> aVendorInfo = getJREInfoByPath(ouPath);
     373         204 :     if (!aVendorInfo.is())
     374           0 :         return JFW_PLUGIN_E_NO_JRE;
     375             : 
     376             :     //Check if the detected JRE matches the version requirements
     377         204 :     if (!ouVendor.equals(aVendorInfo->getVendor()))
     378         102 :         return JFW_PLUGIN_E_NO_JRE;
     379             : 
     380         102 :     if (!ouMinVer.isEmpty())
     381             :     {
     382         102 :         int nRes = 0;
     383             :         try
     384             :         {
     385         102 :             nRes = aVendorInfo->compareVersions(ouMinVer);
     386             :         }
     387           0 :         catch (MalformedVersionException&)
     388             :         {
     389             :             //The minVersion was not recognized as valid for this vendor.
     390             :             JFW_ENSURE(
     391             :                 false,
     392             :                 "[Java framework]sunjavaplugin does not know version: "
     393             :                 + ouMinVer + " for vendor: " + aVendorInfo->getVendor()
     394             :                 + " .Check minimum Version." );
     395           0 :             return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
     396             :         }
     397         102 :         if (nRes < 0)
     398           0 :             return JFW_PLUGIN_E_FAILED_VERSION;
     399             :     }
     400             : 
     401         102 :     if (!ouMaxVer.isEmpty())
     402             :     {
     403           0 :         int nRes = 0;
     404             :         try
     405             :         {
     406           0 :             nRes = aVendorInfo->compareVersions(ouMaxVer);
     407             :         }
     408           0 :         catch (MalformedVersionException&)
     409             :         {
     410             :             //The maxVersion was not recognized as valid for this vendor.
     411             :             JFW_ENSURE(
     412             :                 false,
     413             :                 "[Java framework]sunjavaplugin does not know version: "
     414             :                 + ouMaxVer + " for vendor: " + aVendorInfo->getVendor()
     415             :                 + " .Check maximum Version." );
     416           0 :             return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
     417             :         }
     418           0 :         if (nRes > 0)
     419           0 :             return JFW_PLUGIN_E_FAILED_VERSION;
     420             :     }
     421             : 
     422         102 :     for (int i = 0; i < nLenList; i++)
     423             :     {
     424           0 :         OUString sExVer(arExcludeList[i]);
     425           0 :         int nRes = 0;
     426             :         try
     427             :         {
     428           0 :             nRes = aVendorInfo->compareVersions(sExVer);
     429             :         }
     430           0 :         catch (MalformedVersionException&)
     431             :         {
     432             :             //The excluded version was not recognized as valid for this vendor.
     433             :             JFW_ENSURE(
     434             :                 false,
     435             :                 "[Java framework]sunjavaplugin does not know version: "
     436             :                 + sExVer + " for vendor: " + aVendorInfo->getVendor()
     437             :                 + " .Check excluded versions." );
     438           0 :             return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
     439             :         }
     440           0 :         if (nRes == 0)
     441           0 :             return JFW_PLUGIN_E_FAILED_VERSION;
     442           0 :     }
     443         102 :     *ppInfo = createJavaInfo(aVendorInfo);
     444             : 
     445         306 :     return errorcode;
     446             : }
     447             : 
     448             : #if defined(WNT)
     449             : 
     450             : // Load msvcr71.dll using an explicit full path from where it is
     451             : // present as bundled with the JRE. In case it is not found where we
     452             : // think it should be, do nothing, and just let the implicit loading
     453             : // that happens when loading the JVM take care of it.
     454             : 
     455             : static void load_msvcr(LPCWSTR jvm_dll, wchar_t const* msvcr)
     456             : {
     457             :     wchar_t msvcr_dll[MAX_PATH];
     458             :     wchar_t *slash;
     459             : 
     460             :     if (wcslen(jvm_dll) > MAX_PATH - 15)
     461             :         return;
     462             : 
     463             :     wcscpy(msvcr_dll, jvm_dll);
     464             : 
     465             :     // First check if msvcr71.dll is in the same folder as jvm.dll. It
     466             :     // normally isn't, at least up to 1.6.0_22, but who knows if it
     467             :     // might be in the future.
     468             :     slash = wcsrchr(msvcr_dll, L'\\');
     469             : 
     470             :     if (!slash)
     471             :     {
     472             :         // Huh, weird path to jvm.dll. Oh well.
     473             :         return;
     474             :     }
     475             : 
     476             :     wcscpy(slash+1, msvcr);
     477             :     if (LoadLibraryW(msvcr_dll))
     478             :         return;
     479             : 
     480             :     // Then check if msvcr71.dll is in the parent folder of where
     481             :     // jvm.dll is. That is currently (1.6.0_22) as far as I know the
     482             :     // normal case.
     483             :     *slash = 0;
     484             :     slash = wcsrchr(msvcr_dll, L'\\');
     485             : 
     486             :     if (!slash)
     487             :         return;
     488             : 
     489             :     wcscpy(slash+1, msvcr);
     490             :     LoadLibraryW(msvcr_dll);
     491             : }
     492             : 
     493             : // Check if the jvm DLL imports msvcr71.dll, and in that case try
     494             : // loading it explicitly. In case something goes wrong, do nothing,
     495             : // and just let the implicit loading try to take care of it.
     496             : static void do_msvcr_magic(rtl_uString *jvm_dll)
     497             : {
     498             :     rtl_uString* Module(0);
     499             :     struct stat st;
     500             : 
     501             :     oslFileError nError = osl_getSystemPathFromFileURL(jvm_dll, &Module);
     502             : 
     503             :     if ( osl_File_E_None != nError )
     504             :         rtl_uString_assign(&Module, jvm_dll);
     505             : 
     506             :     FILE *f = _wfopen(reinterpret_cast<LPCWSTR>(Module->buffer), L"rb");
     507             : 
     508             :     if (fstat(fileno(f), &st) == -1)
     509             :     {
     510             :         fclose(f);
     511             :         return;
     512             :     }
     513             : 
     514             :     PIMAGE_DOS_HEADER dos_hdr = (PIMAGE_DOS_HEADER) malloc(st.st_size);
     515             : 
     516             :     if (fread(dos_hdr, st.st_size, 1, f) != 1 ||
     517             :         memcmp(dos_hdr, "MZ", 2) != 0 ||
     518             :         dos_hdr->e_lfanew < 0 ||
     519             :         dos_hdr->e_lfanew > (LONG) (st.st_size - sizeof(IMAGE_NT_HEADERS)))
     520             :     {
     521             :         free(dos_hdr);
     522             :         fclose(f);
     523             :         return;
     524             :     }
     525             : 
     526             :     fclose(f);
     527             : 
     528             :     IMAGE_NT_HEADERS *nt_hdr = (IMAGE_NT_HEADERS *) ((char *)dos_hdr + dos_hdr->e_lfanew);
     529             : 
     530             :     DWORD importsVA = nt_hdr->OptionalHeader
     531             :             .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
     532             :     // first determine Virtual-to-File-address mapping for the section
     533             :     // that contains the import directory
     534             :     IMAGE_SECTION_HEADER *sections = IMAGE_FIRST_SECTION(nt_hdr);
     535             :     ptrdiff_t VAtoPhys = -1;
     536             :     for (int i = 0; i < nt_hdr->FileHeader.NumberOfSections; ++i)
     537             :     {
     538             :         if (sections->VirtualAddress <= importsVA &&
     539             :             importsVA < sections->VirtualAddress + sections->SizeOfRawData)
     540             :         {
     541             :             VAtoPhys = sections->PointerToRawData - sections->VirtualAddress;
     542             :             break;
     543             :         }
     544             :         ++sections;
     545             :     }
     546             :     if (-1 == VAtoPhys) // not found?
     547             :     {
     548             :         free(dos_hdr);
     549             :         return;
     550             :     }
     551             :     IMAGE_IMPORT_DESCRIPTOR *imports =
     552             :         (IMAGE_IMPORT_DESCRIPTOR *) ((char *) dos_hdr + importsVA + VAtoPhys);
     553             : 
     554             :     while (imports <= (IMAGE_IMPORT_DESCRIPTOR *) ((char *) dos_hdr + st.st_size - sizeof (IMAGE_IMPORT_DESCRIPTOR)) &&
     555             :            imports->Name != 0 &&
     556             :            imports->Name + VAtoPhys < (DWORD) st.st_size)
     557             :     {
     558             :         static struct { char const * name; wchar_t const * wname; } msvcrts[] =
     559             :         {
     560             :             { "msvcr71.dll" , L"msvcr71.dll"  },
     561             :             { "msvcr100.dll", L"msvcr100.dll" },
     562             :         };
     563             :         char const* importName = (char *) dos_hdr + imports->Name + VAtoPhys;
     564             :         for (size_t i = 0; i < SAL_N_ELEMENTS(msvcrts); ++i)
     565             :         {
     566             :             if (0 == strnicmp(importName,
     567             :                 // Intentional strlen() + 1 here to include terminating zero
     568             :                         msvcrts[i].name, strlen(msvcrts[i].name) + 1))
     569             :             {
     570             :                 load_msvcr(reinterpret_cast<LPCWSTR>(Module->buffer),
     571             :                         msvcrts[i].wname);
     572             :                 free(dos_hdr);
     573             :                 return;
     574             :             }
     575             :         }
     576             :         imports++;
     577             :     }
     578             : 
     579             :     free(dos_hdr);
     580             : }
     581             : 
     582             : #endif
     583             : 
     584             : /** starts a Java Virtual Machine.
     585             :     <p>
     586             :     The function shall ensure, that the VM does not abort the process
     587             :     during instantiation.
     588             :     </p>
     589             :  */
     590          18 : javaPluginError jfw_plugin_startJavaVirtualMachine(
     591             :     const JavaInfo *pInfo,
     592             :     const JavaVMOption* arOptions,
     593             :     sal_Int32 cOptions,
     594             :     JavaVM ** ppVm,
     595             :     JNIEnv ** ppEnv)
     596             : {
     597             :     // unless guard is volatile the following warning occurs on gcc:
     598             :     // warning: variable 't' might be clobbered by `longjmp' or `vfork'
     599          18 :     volatile osl::MutexGuard guard(PluginMutex::get());
     600             :     // unless errorcode is volatile the following warning occurs on gcc:
     601             :     // warning: variable 'errorcode' might be clobbered by `longjmp' or `vfork'
     602          18 :     volatile javaPluginError errorcode = JFW_PLUGIN_E_NONE;
     603          18 :     if ( pInfo == NULL || ppVm == NULL || ppEnv == NULL)
     604           0 :         return JFW_PLUGIN_E_INVALID_ARG;
     605             :     //Check if the Vendor (pInfo->sVendor) is supported by this plugin
     606          18 :     if ( ! isVendorSupported(pInfo->sVendor))
     607           0 :         return JFW_PLUGIN_E_WRONG_VENDOR;
     608          36 :     OUString sRuntimeLib = getRuntimeLib(pInfo->arVendorData);
     609             :     JFW_TRACE2("Using Java runtime library: " << sRuntimeLib);
     610             : 
     611             : #ifndef ANDROID
     612             :     // On linux we load jvm with RTLD_GLOBAL. This is necessary for debugging, because
     613             :     // libjdwp.so need a symbol (fork1) from libjvm which it only gets if the jvm is loaded
     614             :     // witd RTLD_GLOBAL. On Solaris libjdwp.so is correctly linked with libjvm.so
     615          36 :     osl::Module moduleRt;
     616             : #if defined(LINUX)
     617          18 :     if (!moduleRt.load(sRuntimeLib, SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_NOW))
     618             : #else
     619             : #if defined(WNT)
     620             :     do_msvcr_magic(sRuntimeLib.pData);
     621             : #endif
     622             :     if (!moduleRt.load(sRuntimeLib, SAL_LOADMODULE_DEFAULT))
     623             : #endif
     624             :     {
     625             :         JFW_ENSURE(false,
     626             :                    "[Java framework]sunjavaplugin" SAL_DLLEXTENSION
     627             :                       " could not load Java runtime library: \n"
     628             :                    + sRuntimeLib + "\n");
     629             :         JFW_TRACE0("Could not load Java runtime library: " << sRuntimeLib);
     630           0 :         return JFW_PLUGIN_E_VM_CREATION_FAILED;
     631             :     }
     632             : 
     633             : #if defined UNX && !defined MACOSX
     634             :     //Setting the JAVA_HOME is needed for awt
     635          36 :     OUString sPathLocation;
     636          18 :     osl_getSystemPathFromFileURL(pInfo->sLocation, & sPathLocation.pData);
     637          18 :     osl_setEnvironment(OUString("JAVA_HOME").pData, sPathLocation.pData);
     638             : #endif
     639             : 
     640             :     typedef jint JNICALL JNI_CreateVM_Type(JavaVM **, JNIEnv **, void *);
     641          36 :     OUString sSymbolCreateJava("JNI_CreateJavaVM");
     642             : 
     643             :     JNI_CreateVM_Type * pCreateJavaVM =
     644          18 :         (JNI_CreateVM_Type *)moduleRt.getFunctionSymbol(sSymbolCreateJava);
     645          18 :     if (!pCreateJavaVM)
     646             :     {
     647             :         OSL_ASSERT(false);
     648             :         OString sLib = OUStringToOString(
     649           0 :             sRuntimeLib, osl_getThreadTextEncoding());
     650             :         OString sSymbol = OUStringToOString(
     651           0 :             sSymbolCreateJava, osl_getThreadTextEncoding());
     652             :         fprintf(stderr,"[Java framework]sunjavaplugin" SAL_DLLEXTENSION
     653             :                 "Java runtime library: %s does not export symbol %s !\n",
     654           0 :                 sLib.getStr(), sSymbol.getStr());
     655           0 :         return JFW_PLUGIN_E_VM_CREATION_FAILED;
     656             :     }
     657          18 :     moduleRt.release();
     658             : 
     659             :     // Valgrind typically emits many false errors when executing JIT'ed JVM
     660             :     // code, so force the JVM into interpreted mode:
     661          18 :     bool addForceInterpreted = FORCE_INTERPRETED > 0;
     662             : 
     663             :     // Some testing with Java 1.4 showed that JavaVMOption.optionString has to
     664             :     // be encoded with the system encoding (i.e., osl_getThreadTextEncoding):
     665             :     JavaVMInitArgs vm_args;
     666             : 
     667         494 :     struct Option {
     668          86 :         Option(OString const & theOptionString, void * theExtraInfo):
     669          86 :             optionString(theOptionString), extraInfo(theExtraInfo)
     670          86 :         {}
     671             : 
     672             :         OString optionString;
     673             :         void * extraInfo;
     674             :     };
     675          36 :     std::vector<Option> options;
     676             : 
     677             :     // We set an abort handler which is called when the VM calls _exit during
     678             :     // JNI_CreateJavaVM. This happens when the LD_LIBRARY_PATH does not contain
     679             :     // all some directories of the Java installation. This is necessary for
     680             :     // all versions below 1.5.1
     681          18 :     options.push_back(Option("abort", reinterpret_cast<void*>(abort_handler)));
     682          18 :     bool hasStackSize = false;
     683          86 :     for (int i = 0; i < cOptions; i++)
     684             :     {
     685          68 :         OString opt(arOptions[i].optionString);
     686             : #ifdef UNX
     687             :         // Until java 1.5 we need to put a plugin.jar or javaplugin.jar (<1.4.2)
     688             :         // in the class path in order to have applet support:
     689          68 :         if (opt.startsWith("-Djava.class.path="))
     690             :         {
     691           4 :             OString sAddPath = getPluginJarPath(pInfo->sVendor, pInfo->sLocation,pInfo->sVersion);
     692           4 :             if (!sAddPath.isEmpty())
     693           4 :                 opt += OString(SAL_PATHSEPARATOR) + sAddPath;
     694             :         }
     695             : #endif
     696          68 :         if (opt == "-Xint") {
     697           0 :             addForceInterpreted = false;
     698             :         }
     699          68 :         if (opt.startsWith("-Xss")) {
     700           0 :             hasStackSize = true;
     701             :         }
     702          68 :         options.push_back(Option(opt, arOptions[i].extraInfo));
     703          68 :     }
     704          18 :     if (addForceInterpreted) {
     705           0 :         options.push_back(Option("-Xint", nullptr));
     706             :     }
     707          18 :     if (!hasStackSize) {
     708             : #if defined LINUX && defined X86
     709             :         // At least OpenJDK 1.8.0's os::workaround_expand_exec_shield_cs_limit
     710             :         // (hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp) can mmap an rwx
     711             :         // page into the area that the main stack can grow down to according to
     712             :         // "ulimit -s", as os::init_2's (hotspot/src/os/linux/vm/os_linux.cpp)
     713             :         // call to
     714             :         //
     715             :         //   Linux::capture_initial_stack(JavaThread::stack_size_at_create());
     716             :         //
     717             :         // caps _initial_thread_stack_size at threadStackSizeInBytes ,i.e.,
     718             :         // -Xss, which appears to default to only 327680, whereas "ulimit -s"
     719             :         // defaults to 8192 * 1024 at least on Fedora 20; so attempt to pass in
     720             :         // a useful -Xss argument:
     721             :         rlimit l;
     722             :         if (getrlimit(RLIMIT_STACK, &l) == 0) {
     723             :             if (l.rlim_cur == RLIM_INFINITY) {
     724             :                 SAL_INFO("jfw", "RLIMIT_STACK RLIM_INFINITY -> 8192K");
     725             :                 l.rlim_cur = 8192 * 1024;
     726             :             } else if (l.rlim_cur > 512 * 1024 * 1024) {
     727             :                 SAL_INFO(
     728             :                     "jfw", "huge RLIMIT_STACK " << l.rlim_cur << " -> 8192K");
     729             :                 l.rlim_cur = 8192 * 1024;
     730             :             }
     731             :             options.push_back(
     732             :                 Option("-Xss" + OString::number(l.rlim_cur), nullptr));
     733             :         } else {
     734             :             int e = errno;
     735             :             SAL_WARN("jfw", "getrlimit(RLIMIT_STACK) failed with errno " << e);
     736             :         }
     737             : #endif
     738             :     }
     739             : 
     740          36 :     boost::scoped_array<JavaVMOption> sarOptions(new JavaVMOption[options.size()]);
     741         104 :     for (std::vector<Option>::size_type i = 0; i != options.size(); ++i) {
     742             :         SAL_INFO(
     743             :             "jfw",
     744             :             "VM option \"" << options[i].optionString << "\" "
     745             :                 << options[i].extraInfo);
     746          86 :         sarOptions[i].optionString = const_cast<char *>(
     747          86 :             options[i].optionString.getStr());
     748          86 :         sarOptions[i].extraInfo = options[i].extraInfo;
     749             :     }
     750             : 
     751             : #ifdef MACOSX
     752             :     vm_args.version= JNI_VERSION_1_4; // issue 88987
     753             : #else
     754          18 :     vm_args.version= JNI_VERSION_1_2;
     755             : #endif
     756          18 :     vm_args.options= sarOptions.get();
     757          18 :     vm_args.nOptions= options.size(); //TODO overflow
     758          18 :     vm_args.ignoreUnrecognized= JNI_TRUE;
     759             : 
     760             :     /* We set a global flag which is used by the abort handler in order to
     761             :        determine whether it is  should use longjmp to get back into this function.
     762             :        That is, the abort handler determines if it is on the same stack as this function
     763             :        and then jumps back into this function.
     764             :     */
     765          18 :     g_bInGetJavaVM = 1;
     766             :     jint err;
     767          18 :     JavaVM * pJavaVM = 0;
     768          18 :     memset( jmp_jvm_abort, 0, sizeof(jmp_jvm_abort));
     769          18 :     int jmpval= setjmp( jmp_jvm_abort );
     770             :     /* If jmpval is not "0" then this point was reached by a longjmp in the
     771             :        abort_handler, which was called indirectly by JNI_CreateVM.
     772             :     */
     773          18 :     if( jmpval == 0)
     774             :     {
     775             :         //returns negative number on failure
     776          18 :         err= pCreateJavaVM(&pJavaVM, ppEnv, &vm_args);
     777          18 :         g_bInGetJavaVM = 0;
     778             :     }
     779             :     else
     780             :         // set err to a positive number, so as or recognize that an abort (longjmp)
     781             :         //occurred
     782           0 :         err= 1;
     783             : 
     784          18 :     if(err != 0)
     785             :     {
     786           0 :         if( err < 0)
     787             :         {
     788             :             fprintf(stderr,"[Java framework] sunjavaplugin" SAL_DLLEXTENSION
     789           0 :                     "Can not create Java Virtual Machine\n");
     790           0 :             errorcode = JFW_PLUGIN_E_VM_CREATION_FAILED;
     791             :         }
     792           0 :         else if( err > 0)
     793             :         {
     794             :             fprintf(stderr,"[Java framework] sunjavaplugin" SAL_DLLEXTENSION
     795           0 :                     "Can not create JavaVirtualMachine, abort handler was called.\n");
     796           0 :             errorcode = JFW_PLUGIN_E_VM_CREATION_FAILED;
     797             :         }
     798             :     }
     799             :     else
     800             :     {
     801          18 :         *ppVm = pJavaVM;
     802             :         JFW_TRACE2("JVM created");
     803             :     }
     804             : #else
     805             :     (void) arOptions;
     806             :     (void) cOptions;
     807             :     // On Android we always have a Java VM as we only expect this code
     808             :     // to be run in an Android app anyway.
     809             :     *ppVm = lo_get_javavm();
     810             :     fprintf(stderr, "lo_get_javavm returns %p", *ppVm);
     811             : #endif
     812             : 
     813          36 :    return errorcode;
     814             : }
     815             : 
     816          98 : javaPluginError jfw_plugin_existJRE(const JavaInfo *pInfo, sal_Bool *exist)
     817             : {
     818          98 :     javaPluginError ret = JFW_PLUGIN_E_NONE;
     819          98 :     if (!pInfo || !exist)
     820           0 :         return JFW_PLUGIN_E_INVALID_ARG;
     821          98 :     OUString sLocation(pInfo->sLocation);
     822             : 
     823          98 :     if (sLocation.isEmpty())
     824           0 :         return JFW_PLUGIN_E_INVALID_ARG;
     825         196 :     ::osl::DirectoryItem item;
     826          98 :     ::osl::File::RC rc_item = ::osl::DirectoryItem::get(sLocation, item);
     827          98 :     if (::osl::File::E_None == rc_item)
     828             :     {
     829          98 :         *exist = sal_True;
     830             :     }
     831           0 :     else if (::osl::File::E_NOENT == rc_item)
     832             :     {
     833           0 :         *exist = sal_False;
     834             :     }
     835             :     else
     836             :     {
     837           0 :         ret = JFW_PLUGIN_E_ERROR;
     838             :     }
     839             :     //We can have the situation that the JavaVM runtime library is not
     840             :     //contained within JAVA_HOME. Then the check for JAVA_HOME would return
     841             :     //true although the runtime library may not be loadable.
     842             :     //Or the JAVA_HOME directory of a deinstalled JRE left behind.
     843          98 :     if (ret == JFW_PLUGIN_E_NONE && *exist == sal_True)
     844             :     {
     845          98 :         OUString sRuntimeLib = getRuntimeLib(pInfo->arVendorData);
     846             :         JFW_TRACE2("Checking existence of Java runtime library");
     847             : 
     848         196 :         ::osl::DirectoryItem itemRt;
     849          98 :         ::osl::File::RC rc_itemRt = ::osl::DirectoryItem::get(sRuntimeLib, itemRt);
     850          98 :         if (::osl::File::E_None == rc_itemRt)
     851             :         {
     852          98 :             *exist = sal_True;
     853             :             JFW_TRACE2("Java runtime library exist: " << sRuntimeLib);
     854             : 
     855             :         }
     856           0 :         else if (::osl::File::E_NOENT == rc_itemRt)
     857             :         {
     858           0 :             *exist = sal_False;
     859             :             JFW_TRACE2("Java runtime library does not exist: " << sRuntimeLib);
     860             :         }
     861             :         else
     862             :         {
     863           0 :             ret = JFW_PLUGIN_E_ERROR;
     864             :             JFW_TRACE2("Error while looking for Java runtime library: " << sRuntimeLib);
     865          98 :         }
     866             :     }
     867         196 :     return ret;
     868             : }
     869             : 
     870             : 
     871             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10