Skip to content

Commit 035ee5c

Browse files
authored
Refactor external_assembly_probe to be separate from single-file bundle probing (#113356)
External assembly probing is not inherently tied to the idea of a bundle. This separates having an external assembly probe callback from the bundle / bundle file location idea and refactors the hooks into assembly loading into an AssemblyProbeExtension helper that handles both bundle and external assembly probing.
1 parent 9c9178f commit 035ee5c

21 files changed

+264
-141
lines changed

src/coreclr/binder/assemblybindercommon.cpp

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ extern HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadCon
3737

3838
STDAPI BinderAcquirePEImage(LPCTSTR szAssemblyPath,
3939
PEImage** ppPEImage,
40-
BundleFileLocation bundleFileLocation);
40+
ProbeExtensionResult probeExtensionResult);
4141

4242
namespace BINDER_SPACE
4343
{
@@ -271,8 +271,8 @@ namespace BINDER_SPACE
271271
StackSString sCoreLibName(CoreLibName_IL_W);
272272
StackSString sCoreLib;
273273
BinderTracing::PathSource pathSource = BinderTracing::PathSource::Bundle;
274-
BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(sCoreLibName, /*pathIsBundleRelative */ true);
275-
if (!bundleFileLocation.IsValid())
274+
ProbeExtensionResult probeExtensionResult = AssemblyProbeExtension::Probe(sCoreLibName, /*pathIsBundleRelative */ true);
275+
if (!probeExtensionResult.IsValid())
276276
{
277277
pathSource = BinderTracing::PathSource::ApplicationAssemblies;
278278
}
@@ -282,7 +282,7 @@ namespace BINDER_SPACE
282282
hr = AssemblyBinderCommon::GetAssembly(sCoreLib,
283283
TRUE /* fIsInTPA */,
284284
&pSystemAssembly,
285-
bundleFileLocation);
285+
probeExtensionResult);
286286

287287
BinderTracing::PathProbed(sCoreLib, pathSource, hr);
288288

@@ -322,7 +322,7 @@ namespace BINDER_SPACE
322322
hr = AssemblyBinderCommon::GetAssembly(sCoreLib,
323323
TRUE /* fIsInTPA */,
324324
&pSystemAssembly,
325-
bundleFileLocation);
325+
probeExtensionResult);
326326

327327
BinderTracing::PathProbed(sCoreLib, BinderTracing::PathSource::ApplicationAssemblies, hr);
328328
}
@@ -367,8 +367,8 @@ namespace BINDER_SPACE
367367
StackSString sCoreLibSatellite;
368368

369369
BinderTracing::PathSource pathSource = BinderTracing::PathSource::Bundle;
370-
BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(relativePath, /*pathIsBundleRelative */ true);
371-
if (!bundleFileLocation.IsValid())
370+
ProbeExtensionResult probeExtensionResult = AssemblyProbeExtension::Probe(relativePath, /*pathIsBundleRelative */ true);
371+
if (!probeExtensionResult.IsValid())
372372
{
373373
sCoreLibSatellite.Set(systemDirectory);
374374
pathSource = BinderTracing::PathSource::ApplicationAssemblies;
@@ -379,7 +379,7 @@ namespace BINDER_SPACE
379379
IF_FAIL_GO(AssemblyBinderCommon::GetAssembly(sCoreLibSatellite,
380380
TRUE /* fIsInTPA */,
381381
&pSystemAssembly,
382-
bundleFileLocation));
382+
probeExtensionResult));
383383
BinderTracing::PathProbed(sCoreLibSatellite, pathSource, hr);
384384

385385
*ppSystemAssembly = pSystemAssembly.Extract();
@@ -590,15 +590,15 @@ namespace BINDER_SPACE
590590

591591
namespace
592592
{
593-
HRESULT BindSatelliteResourceFromBundle(
593+
HRESULT BindSatelliteResourceByProbeExtension(
594594
AssemblyName* pRequestedAssemblyName,
595595
SString &relativePath,
596596
BindResult* pBindResult)
597597
{
598598
HRESULT hr = S_OK;
599599

600-
BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(relativePath, /* pathIsBundleRelative */ true);
601-
if (!bundleFileLocation.IsValid())
600+
ProbeExtensionResult probeExtensionResult = AssemblyProbeExtension::Probe(relativePath, /* pathIsBundleRelative */ true);
601+
if (!probeExtensionResult.IsValid())
602602
{
603603
return hr;
604604
}
@@ -607,7 +607,7 @@ namespace BINDER_SPACE
607607
hr = AssemblyBinderCommon::GetAssembly(relativePath,
608608
FALSE /* fIsInTPA */,
609609
&pAssembly,
610-
bundleFileLocation);
610+
probeExtensionResult);
611611

612612
BinderTracing::PathProbed(relativePath, BinderTracing::PathSource::Bundle, hr);
613613

@@ -692,7 +692,7 @@ namespace BINDER_SPACE
692692
BindResult* pBindResult)
693693
{
694694
// Satellite resource probing strategy is to look:
695-
// * First within the single-file bundle
695+
// * First via probe extensions (single-file bundle, external data)
696696
// * Then under each of the Platform Resource Roots
697697
// * Then under each of the App Paths.
698698
//
@@ -712,7 +712,7 @@ namespace BINDER_SPACE
712712
CombinePath(fileName, simpleNameRef, fileName);
713713
fileName.Append(W(".dll"));
714714

715-
hr = BindSatelliteResourceFromBundle(pRequestedAssemblyName, fileName, pBindResult);
715+
hr = BindSatelliteResourceByProbeExtension(pRequestedAssemblyName, fileName, pBindResult);
716716

717717
if (pBindResult->HaveResult() || FAILED(hr))
718718
{
@@ -841,12 +841,9 @@ namespace BINDER_SPACE
841841
ReleaseHolder<Assembly> pTPAAssembly;
842842
const SString& simpleName = pRequestedAssemblyName->GetSimpleName();
843843

844-
// Is assembly in the bundle?
845-
// Single-file bundle contents take precedence over TPA.
846-
// The list of bundled assemblies is contained in the bundle manifest, and NOT in the TPA.
847-
// Therefore the bundle is first probed using the assembly's simple name.
848-
// If found, the assembly is loaded from the bundle.
849-
if (Bundle::AppIsBundle())
844+
// Probing extensions (single-file, external probe) take precedence over TPA.
845+
// For single-file, bundled assemblies should only be in the bundle manifest, not in the TPA.
846+
if (AssemblyProbeExtension::IsEnabled())
850847
{
851848
// Search Assembly.ni.dll, then Assembly.dll
852849
// The Assembly.ni.dll paths are rare, and intended for supporting managed C++ R2R assemblies.
@@ -858,16 +855,16 @@ namespace BINDER_SPACE
858855
SString assemblyFileName(simpleName);
859856
assemblyFileName.Append(candidates[i]);
860857

861-
SString assemblyFilePath(Bundle::AppBundle->BasePath());
862-
assemblyFilePath.Append(assemblyFileName);
863-
864-
BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(assemblyFileName, /* pathIsBundleRelative */ true);
865-
if (bundleFileLocation.IsValid())
858+
ProbeExtensionResult probeExtensionResult = AssemblyProbeExtension::Probe(assemblyFileName, /* pathIsBundleRelative */ true);
859+
if (probeExtensionResult.IsValid())
866860
{
861+
SString assemblyFilePath(Bundle::AppIsBundle() ? Bundle::AppBundle->BasePath() : SString::Empty());
862+
assemblyFilePath.Append(assemblyFileName);
863+
867864
hr = GetAssembly(assemblyFilePath,
868865
TRUE, // fIsInTPA
869866
&pTPAAssembly,
870-
bundleFileLocation);
867+
probeExtensionResult);
871868

872869
BinderTracing::PathProbed(assemblyFilePath, BinderTracing::PathSource::Bundle, hr);
873870

@@ -996,7 +993,7 @@ namespace BINDER_SPACE
996993
HRESULT AssemblyBinderCommon::GetAssembly(SString &assemblyPath,
997994
BOOL fIsInTPA,
998995
Assembly **ppAssembly,
999-
BundleFileLocation bundleFileLocation)
996+
ProbeExtensionResult probeExtensionResult)
1000997
{
1001998
HRESULT hr = S_OK;
1002999

@@ -1012,7 +1009,7 @@ namespace BINDER_SPACE
10121009
{
10131010
LPCTSTR szAssemblyPath = const_cast<LPCTSTR>(assemblyPath.GetUnicode());
10141011

1015-
hr = BinderAcquirePEImage(szAssemblyPath, &pPEImage, bundleFileLocation);
1012+
hr = BinderAcquirePEImage(szAssemblyPath, &pPEImage, probeExtensionResult);
10161013
IF_FAIL_GO(hr);
10171014
}
10181015

src/coreclr/binder/inc/assembly.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include "customassemblybinder.h"
2626
#endif // !defined(DACCESS_COMPILE)
2727

28-
#include "bundle.h"
2928
#include <assemblybinderutil.h>
3029

3130
namespace BINDER_SPACE

src/coreclr/binder/inc/assemblybindercommon.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#include "bindertypes.hpp"
1818
#include "bindresult.hpp"
19-
#include "bundle.h"
19+
#include <assemblyprobeextension.h>
2020

2121
class AssemblyBinder;
2222
class DefaultAssemblyBinder;
@@ -28,7 +28,7 @@ namespace BINDER_SPACE
2828
class AssemblyBinderCommon
2929
{
3030
public:
31-
static HRESULT BindAssembly(/* in */ AssemblyBinder *pBinder,
31+
static HRESULT BindAssembly(/* in */ AssemblyBinder *pBinder,
3232
/* in */ AssemblyName *pAssemblyName,
3333
/* in */ bool excludeAppPaths,
3434
/* out */ Assembly **ppAssembly);
@@ -44,7 +44,7 @@ namespace BINDER_SPACE
4444
static HRESULT GetAssembly(/* in */ SString &assemblyPath,
4545
/* in */ BOOL fIsInTPA,
4646
/* out */ Assembly **ppAssembly,
47-
/* in */ BundleFileLocation bundleFileLocation = BundleFileLocation::Invalid());
47+
/* in */ ProbeExtensionResult probeExtensionResult = ProbeExtensionResult::Invalid());
4848

4949
#if !defined(DACCESS_COMPILE)
5050
static HRESULT BindUsingHostAssemblyResolver (/* in */ INT_PTR pManagedAssemblyLoadContextToBindWithin,

src/coreclr/dlls/mscoree/exports.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -288,12 +288,9 @@ int coreclr_initialize(
288288
hr = CorHost2::CreateObject(IID_ICLRRuntimeHost4, (void**)&host);
289289
IfFailRet(hr);
290290

291-
ConstWStringHolder appDomainFriendlyNameW = StringToUnicode(appDomainFriendlyName);
292-
293-
ExternalAssemblyProbeFn* externalAssemblyProbe = hostContract != nullptr ? hostContract->external_assembly_probe : nullptr;
294-
if (bundleProbe != nullptr || externalAssemblyProbe != nullptr)
291+
if (bundleProbe != nullptr)
295292
{
296-
static Bundle bundle(exePath, bundleProbe, externalAssemblyProbe);
293+
static Bundle bundle(exePath, bundleProbe);
297294
Bundle::AppBundle = &bundle;
298295
}
299296

@@ -309,6 +306,7 @@ int coreclr_initialize(
309306
hr = host->Start();
310307
IfFailRet(hr);
311308

309+
ConstWStringHolder appDomainFriendlyNameW = StringToUnicode(appDomainFriendlyName);
312310
hr = host->CreateAppDomainWithManager(
313311
appDomainFriendlyNameW,
314312
0,
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#ifndef HAVE_ASSEMBLY_PROBE_EXTENSIONS_H
5+
#define HAVE_ASSEMBLY_PROBE_EXTENSIONS_H
6+
7+
#include <sstring.h>
8+
#include "bundle.h"
9+
10+
class ProbeExtensionResult
11+
{
12+
public:
13+
enum class Type
14+
{
15+
Invalid,
16+
Bundle,
17+
External,
18+
};
19+
20+
Type Type;
21+
union
22+
{
23+
BundleFileLocation BundleLocation;
24+
struct
25+
{
26+
void* Data;
27+
int64_t Size;
28+
} ExternalData;
29+
};
30+
31+
ProbeExtensionResult()
32+
: Type{Type::Invalid}
33+
{ }
34+
35+
static ProbeExtensionResult Bundle(BundleFileLocation location)
36+
{
37+
return ProbeExtensionResult(location);
38+
}
39+
40+
static ProbeExtensionResult External(void* data, int64_t size)
41+
{
42+
return ProbeExtensionResult(data, size);
43+
}
44+
45+
static ProbeExtensionResult Invalid() { LIMITED_METHOD_CONTRACT; return ProbeExtensionResult(); }
46+
47+
bool IsValid() const { return Type != Type::Invalid; }
48+
49+
private:
50+
ProbeExtensionResult(BundleFileLocation location)
51+
: Type{Type::Bundle}
52+
, BundleLocation{location}
53+
{ }
54+
55+
ProbeExtensionResult(void* data, int64_t size)
56+
: Type{Type::External}
57+
, ExternalData{data, size}
58+
{ }
59+
};
60+
61+
class AssemblyProbeExtension
62+
{
63+
public:
64+
static bool IsEnabled();
65+
static ProbeExtensionResult Probe(const SString& path, bool pathIsBundleRelative = false);
66+
};
67+
68+
#endif // HAVE_ASSEMBLY_PROBE_EXTENSIONS_H

src/coreclr/inc/bundle.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,29 @@ class Bundle;
1818
struct BundleFileLocation
1919
{
2020
INT64 Size;
21-
void* DataStart;
2221
INT64 Offset;
23-
INT64 UncompresedSize;
22+
INT64 UncompressedSize;
2423

2524
BundleFileLocation()
2625
{
2726
LIMITED_METHOD_CONTRACT;
2827

2928
Size = 0;
30-
DataStart = nullptr;
3129
Offset = 0;
32-
UncompresedSize = 0;
30+
UncompressedSize = 0;
3331
}
3432

3533
static BundleFileLocation Invalid() { LIMITED_METHOD_CONTRACT; return BundleFileLocation(); }
3634

3735
const SString &Path() const;
3836

39-
bool IsValid() const { LIMITED_METHOD_CONTRACT; return DataStart != nullptr || Offset != 0; }
37+
bool IsValid() const { LIMITED_METHOD_CONTRACT; return Offset != 0; }
4038
};
4139

4240
class Bundle
4341
{
4442
public:
45-
Bundle(LPCSTR bundlePath, BundleProbeFn *probe, ExternalAssemblyProbeFn* externalAssemblyProbe = nullptr);
43+
Bundle(LPCSTR bundlePath, BundleProbeFn *probe);
4644
BundleFileLocation Probe(const SString& path, bool pathIsBundleRelative = false) const;
4745

4846
const SString &Path() const { LIMITED_METHOD_CONTRACT; return m_path; }
@@ -53,9 +51,8 @@ class Bundle
5351
static BundleFileLocation ProbeAppBundle(const SString& path, bool pathIsBundleRelative = false);
5452

5553
private:
56-
SString m_path; // The path to single-file executable or package name/id on Android
54+
SString m_path; // The path to single-file executable
5755
BundleProbeFn *m_probe;
58-
ExternalAssemblyProbeFn *m_externalAssemblyProbe;
5956

6057
SString m_basePath; // The prefix to denote a path within the bundle
6158
COUNT_T m_basePathLength;

src/coreclr/inc/hostinformation.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ class HostInformation
1111
public:
1212
static void SetContract(_In_ host_runtime_contract* hostContract);
1313
static bool GetProperty(_In_z_ const char* name, SString& value);
14+
15+
static bool HasExternalProbe();
16+
static bool ExternalAssemblyProbe(_In_ const SString& path, _Out_ void** data, _Out_ int64_t* size);
1417
};
1518

1619
#endif // _HOSTINFORMATION_H_

src/coreclr/vm/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ set(VM_SOURCES_WKS
293293
${VM_SOURCES_DAC_AND_WKS_COMMON}
294294
appdomainnative.cpp
295295
assemblynative.cpp
296+
assemblyprobeextension.cpp
296297
assemblyspec.cpp
297298
baseassemblyspec.cpp
298299
${RUNTIME_DIR}/CachedInterfaceDispatch.cpp
@@ -390,6 +391,7 @@ set(VM_HEADERS_WKS
390391
../inc/jithelpers.h
391392
appdomainnative.hpp
392393
assemblynative.hpp
394+
../inc/assemblyprobeextension.h
393395
assemblyspec.hpp
394396
assemblyspecbase.h
395397
baseassemblyspec.h

src/coreclr/vm/assemblynative.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyB
191191

192192
if (pwzILPath != NULL)
193193
{
194-
pILImage = PEImage::OpenImage(pwzILPath,
195-
MDInternalImport_Default,
196-
BundleFileLocation::Invalid());
194+
pILImage = PEImage::OpenImage(pwzILPath);
197195

198196
// Need to verify that this is a valid CLR assembly.
199197
if (!pILImage->CheckILFormat())

0 commit comments

Comments
 (0)