22
33namespace Consyzer . Core . Resolvers . Platform ;
44
5- internal sealed class LinuxLibraryResolutionResolver ( string analyzedDirectory )
6- : PlatformLibraryResolutionResolverBase
5+ internal sealed class LinuxLibraryResolutionResolver (
6+ string analyzedDirectory
7+ ) : PlatformLibraryResolutionResolverBase
78{
9+ private const string LibraryExtension = ".so" ;
10+ private const string EnvironmentVariablePath = "LD_LIBRARY_PATH" ;
11+
812 private readonly string _analyzedDirectory = Path . GetFullPath ( analyzedDirectory ) ;
913
1014 // Linux has a lot of mechanisms we can't simulate.
@@ -14,7 +18,6 @@ internal sealed class LinuxLibraryResolutionResolver(string analyzedDirectory)
1418 | NotSimulatedMechanisms . LinuxLdSoConf
1519 | NotSimulatedMechanisms . LinuxSecureExecution
1620 | NotSimulatedMechanisms . LinuxTransitiveDependencies
17- | NotSimulatedMechanisms . LinuxMultiarchDefaultPaths
1821 | NotSimulatedMechanisms . LinuxLdPreload ;
1922
2023 private static readonly string [ ] DefaultSystemLocations =
@@ -23,46 +26,59 @@ internal sealed class LinuxLibraryResolutionResolver(string analyzedDirectory)
2326 "/usr/lib" ,
2427 "/lib64" ,
2528 "/usr/lib64" ,
26- "/usr/local/lib"
29+ "/usr/local/lib" ,
30+ "/lib/x86_64-linux-gnu" ,
31+ "/usr/lib/x86_64-linux-gnu" ,
32+ "/lib/aarch64-linux-gnu" ,
33+ "/usr/lib/aarch64-linux-gnu" ,
34+ "/lib/arm-linux-gnueabihf" ,
35+ "/usr/lib/arm-linux-gnueabihf"
2736 ] ;
2837
2938 public override LibraryResolutionResult Resolve ( string file )
3039 {
31- var normalized = NormalizeLibraryName ( file ) ;
32-
33- // TO DO: make state-machine
40+ var candidates = GetLibraryNameCandidates ( file ) ;
41+ var heuristicCandidates = IsExplicitPath ( candidates [ 0 ] )
42+ ? [ ]
43+ : CollectHeuristicCandidates ( candidates ) ;
3444
35- if ( TryResolveExplicit ( file , normalized , out var result ) ) return result ;
36- if ( TryResolveLdLibraryPath ( file , normalized , out result ) ) return result ;
37- if ( TryResolveDefaultSystemLocations ( file , normalized , out result ) ) return result ;
45+ if ( TryResolveExplicit ( file , candidates [ 0 ] , heuristicCandidates , out var result ) ) return result ;
46+ if ( TryResolveLdLibraryPath ( file , candidates , heuristicCandidates , out result ) ) return result ;
47+ if ( TryResolveDefaultSystemLocations ( file , candidates , heuristicCandidates , out result ) ) return result ;
3848
39- return CreateInconclusive ( file , CollectHeuristicCandidates ( normalized ) , NotSimulated ) ;
49+ return CreateInconclusive ( file , heuristicCandidates , NotSimulated ) ;
4050 }
4151
42- private static bool TryResolveExplicit ( string requestedName , string normalized , out LibraryResolutionResult result )
52+ private static bool TryResolveExplicit (
53+ string requestedName ,
54+ string normalizedExplicitPath ,
55+ IReadOnlyList < string > heuristicCandidates ,
56+ out LibraryResolutionResult result
57+ )
4358 {
44- if ( ! TryGetExplicitPathCandidate ( normalized , out var candidate ) )
59+ if ( ! TryGetExplicitPathCandidate ( normalizedExplicitPath , out var candidate ) )
4560 {
4661 result = default ! ;
4762 return false ;
4863 }
4964
5065 result = candidate is not null
51- ? CreateResolved ( requestedName , candidate , MechanismKind . ExplicitPath )
52- : CreateMissing ( requestedName ) ;
66+ ? CreateResolved ( requestedName , candidate , MechanismKind . ExplicitPath , heuristicCandidates )
67+ : CreateMissing ( requestedName , heuristicCandidates ) ;
5368
5469 return true ;
5570 }
5671
5772 private static bool TryResolveLdLibraryPath (
58- string requestedName ,
59- string normalized ,
73+ string requestedName ,
74+ IReadOnlyList < string > candidates ,
75+ IReadOnlyList < string > heuristicCandidates ,
6076 out LibraryResolutionResult result
6177 )
6278 {
6379 var candidate = TryResolveInDirectories (
64- normalized ,
65- SplitSearchPath ( Environment . GetEnvironmentVariable ( "LD_LIBRARY_PATH" ) )
80+ candidates ,
81+ SplitSearchPath ( Environment . GetEnvironmentVariable ( EnvironmentVariablePath ) )
6682 ) ;
6783
6884 if ( candidate is null )
@@ -71,50 +87,66 @@ out LibraryResolutionResult result
7187 return false ;
7288 }
7389
74- result = CreateResolved ( requestedName , candidate , MechanismKind . EnvironmentOverride ) ;
90+ result = CreateResolved ( requestedName , candidate , MechanismKind . EnvironmentOverride , heuristicCandidates ) ;
7591 return true ;
7692 }
7793
7894 private static bool TryResolveDefaultSystemLocations (
79- string requestedName ,
80- string normalized ,
95+ string requestedName ,
96+ IReadOnlyList < string > candidates ,
97+ IReadOnlyList < string > heuristicCandidates ,
8198 out LibraryResolutionResult result
8299 )
83100 {
84- var candidate = TryResolveInDirectories ( normalized , DefaultSystemLocations ) ;
101+ var candidate = TryResolveInDirectories ( candidates , DefaultSystemLocations ) ;
85102 if ( candidate is null )
86103 {
87104 result = default ! ;
88105 return false ;
89106 }
90107
91- result = CreateResolved ( requestedName , candidate , MechanismKind . DefaultSystemLocations ) ;
108+ result = CreateResolved ( requestedName , candidate , MechanismKind . DefaultSystemLocations , heuristicCandidates ) ;
92109 return true ;
93110 }
94111
95- private static string NormalizeLibraryName ( string input )
112+ private static IReadOnlyList < string > GetLibraryNameCandidates ( string input )
96113 {
97- // Keep as-is if extension exists or contains ".so" somewhere (covers "libm.so.6" too).
98- if ( Path . HasExtension ( input ) || input . Contains ( ".so" , StringComparison . Ordinal ) )
114+ if ( IsExplicitPath ( input ) )
115+ {
116+ return [ input ] ;
117+ }
118+
119+ if ( EndsWithSharedObjectName ( input ) )
99120 {
100- return input ;
121+ var extensioned = input + LibraryExtension ;
122+ return DistinctCandidates (
123+ [
124+ input ,
125+ WithLibPrefix ( input ) ,
126+ extensioned ,
127+ WithLibPrefix ( extensioned )
128+ ] , StringComparer . Ordinal ) ;
101129 }
102130
103- var extensioned = Path . ChangeExtension ( input , "so" ) ;
131+ var canonical = input + LibraryExtension ;
104132
105- return input . StartsWith ( "lib" , StringComparison . Ordinal )
106- ? extensioned
107- : "lib" + extensioned ;
133+ return DistinctCandidates (
134+ [
135+ canonical ,
136+ WithLibPrefix ( canonical ) ,
137+ input ,
138+ WithLibPrefix ( input )
139+ ] , StringComparer . Ordinal ) ;
108140 }
109141
110- private string [ ] CollectHeuristicCandidates ( string normalized )
111- {
112- string ? a = GetCandidatePath ( _analyzedDirectory , normalized ) ;
113- string ? b = GetCandidatePath ( Directory . GetCurrentDirectory ( ) , normalized ) ;
142+ private static bool EndsWithSharedObjectName ( string input )
143+ => input . EndsWith ( LibraryExtension , StringComparison . Ordinal )
144+ || input . Contains ( LibraryExtension , StringComparison . Ordinal ) ;
114145
115- if ( a is null && b is null ) return [ ] ;
116- if ( a is null ) return [ b ! ] ;
117- if ( b is null ) return [ a ] ;
118- return [ a , b ] ;
146+ private static string WithLibPrefix ( string input ) => "lib" + input ;
147+
148+ private IReadOnlyList < string > CollectHeuristicCandidates ( IReadOnlyList < string > candidates )
149+ {
150+ return CollectCandidatePaths ( candidates , _analyzedDirectory , Directory . GetCurrentDirectory ( ) ) ;
119151 }
120- }
152+ }
0 commit comments