Skip to content

Commit 0ad4118

Browse files
committed
Managed side
1 parent 7c1d78a commit 0ad4118

File tree

6 files changed

+57
-24
lines changed

6 files changed

+57
-24
lines changed

src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ sealed class DSOCacheEntry
6161
[NativeAssembler (NumberFormat = LlvmIrVariableNumberFormat.Hexadecimal)]
6262
public ulong real_name_hash;
6363
public bool ignore;
64+
public bool is_jni_library;
6465

6566
[NativeAssembler (UsesDataProvider = true)]
6667
public string name;
@@ -357,7 +358,7 @@ void HashAndSortDSOCache (LlvmIrVariable variable, LlvmIrModuleTarget target, ob
357358

358359
(List<StructureInstance<DSOCacheEntry>> dsoCache, List<StructureInstance<DSOCacheEntry>> aotDsoCache) InitDSOCache ()
359360
{
360-
var dsos = new List<(string name, string nameLabel, bool ignore)> ();
361+
var dsos = new List<(string name, string nameLabel, bool ignore, ITaskItem item)> ();
361362
var nameCache = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
362363

363364
foreach (ITaskItem item in NativeLibraries) {
@@ -371,7 +372,7 @@ void HashAndSortDSOCache (LlvmIrVariable variable, LlvmIrModuleTarget target, ob
371372
continue;
372373
}
373374

374-
dsos.Add ((name, $"dsoName{dsos.Count.ToString (CultureInfo.InvariantCulture)}", ELFHelper.IsEmptyAOTLibrary (Log, item.ItemSpec)));
375+
dsos.Add ((name, $"dsoName{dsos.Count.ToString (CultureInfo.InvariantCulture)}", ELFHelper.IsEmptyAOTLibrary (Log, item.ItemSpec), item));
375376
}
376377

377378
var dsoCache = new List<StructureInstance<DSOCacheEntry>> ();
@@ -388,6 +389,7 @@ void HashAndSortDSOCache (LlvmIrVariable variable, LlvmIrModuleTarget target, ob
388389
HashedName = entryName,
389390
hash = 0, // Hash is arch-specific, we compute it before writing
390391
ignore = dsos[i].ignore,
392+
is_jni_library = ELFHelper.IsJniLibrary (Log, dsos[i].item.ItemSpec),
391393
name = name,
392394
};
393395

src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ sealed class DSOCacheEntry
5959
[NativeAssembler (NumberFormat = LlvmIrVariableNumberFormat.Hexadecimal)]
6060
public ulong real_name_hash;
6161
public bool ignore;
62+
public bool is_jni_library;
6263

6364
[NativeAssembler (UsesDataProvider = true)]
6465
public uint name_index;
@@ -261,10 +262,10 @@ sealed class XamarinAndroidBundledAssembly
261262
StructureInfo? assemblyStoreRuntimeDataStructureInfo;
262263
StructureInfo? runtimePropertyStructureInfo;
263264
StructureInfo? runtimePropertyIndexEntryStructureInfo;
264-
#pragma warning disable CS0169 // Field is never used - might be used in future versions
265+
#pragma warning disable CS0169 // Field is never used - might be used in future versions
265266
StructureInfo? hostConfigurationPropertyStructureInfo;
266267
#pragma warning restore CS0169
267-
#pragma warning disable CS0169 // Field is never used - might be used in future versions
268+
#pragma warning disable CS0169 // Field is never used - might be used in future versions
268269
StructureInfo? hostConfigurationPropertiesStructureInfo;
269270
#pragma warning restore CS0169
270271
StructureInfo? appEnvironmentVariableStructureInfo;
@@ -566,7 +567,7 @@ void HashAndSortDSOCache (LlvmIrVariable variable, LlvmIrModuleTarget target, ob
566567
(List<StructureInstance<DSOCacheEntry>> dsoCache, List<StructureInstance<DSOCacheEntry>> aotDsoCache, LlvmIrStringBlob namesBlob)
567568
InitDSOCache ()
568569
{
569-
var dsos = new List<(string name, string nameLabel, bool ignore)> ();
570+
var dsos = new List<(string name, string nameLabel, bool ignore, ITaskItem item)> ();
570571
var nameCache = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
571572

572573
foreach (ITaskItem item in NativeLibraries) {
@@ -580,7 +581,7 @@ void HashAndSortDSOCache (LlvmIrVariable variable, LlvmIrModuleTarget target, ob
580581
continue;
581582
}
582583

583-
dsos.Add ((name, $"dsoName{dsos.Count.ToString (CultureInfo.InvariantCulture)}", ELFHelper.IsEmptyAOTLibrary (Log, item.ItemSpec)));
584+
dsos.Add ((name, $"dsoName{dsos.Count.ToString (CultureInfo.InvariantCulture)}", ELFHelper.IsEmptyAOTLibrary (Log, item.ItemSpec), item));
584585
}
585586

586587
var dsoCache = new List<StructureInstance<DSOCacheEntry>> ();
@@ -602,6 +603,7 @@ void HashAndSortDSOCache (LlvmIrVariable variable, LlvmIrModuleTarget target, ob
602603

603604
hash = 0, // Hash is arch-specific, we compute it before writing
604605
ignore = dsos[i].ignore,
606+
is_jni_library = ELFHelper.IsJniLibrary (Log, dsos[i].item.ItemSpec),
605607
name_index = (uint)nameOffset,
606608
};
607609

src/Xamarin.Android.Build.Tasks/Utilities/ELFHelper.cs

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ public static bool IsEmptyAOTLibrary (TaskLoggingHelper log, string path)
112112
}
113113

114114
try {
115-
return IsEmptyAOTLibrary (log, path, ELFReader.Load (path));
115+
using IELF elf = ELFReader.Load (path);
116+
return IsEmptyAOTLibrary (log, path, elf);
116117
} catch (Exception ex) {
117118
log.LogWarning ($"Attempt to check whether '{path}' is a valid ELF file failed with exception, ignoring AOT check for the file.");
118119
log.LogWarningFromException (ex, showStackTrace: true);
@@ -126,7 +127,7 @@ public static bool ReferencesLibrary (string libraryPath, string referencedLibra
126127
return false;
127128
}
128129

129-
IELF elf = ELFReader.Load (libraryPath);
130+
using IELF elf = ELFReader.Load (libraryPath);
130131
var dynstr = GetSection (elf, ".dynstr") as IStringTable;
131132
if (dynstr == null) {
132133
return false;
@@ -143,6 +144,44 @@ public static bool ReferencesLibrary (string libraryPath, string referencedLibra
143144
return false;
144145
}
145146

147+
public static bool LibraryHasSymbol (TaskLoggingHelper log, string elfPath, string sectionName, string symbolName, ELFSymbolType symbolType = ELFSymbolType.NotSpecified)
148+
{
149+
if (elfPath.IsNullOrEmpty () || !File.Exists (elfPath)) {
150+
return false;
151+
}
152+
153+
try {
154+
using IELF elf = ELFReader.Load (elfPath);
155+
return HasSymbol (elf, sectionName, symbolName, symbolType);
156+
} catch (Exception ex) {
157+
log.LogWarning ($"Attempt to check whether '{elfPath}' is a valid ELF file failed with exception, ignoring symbol '{symbolName}@{sectionName}' check for the file.");
158+
log.LogWarningFromException (ex, showStackTrace: true);
159+
return false;
160+
}
161+
}
162+
163+
public static bool LibraryHasPublicSymbol (TaskLoggingHelper log, string elfPath, string symbolName, ELFSymbolType symbolType = ELFSymbolType.NotSpecified) => LibraryHasSymbol (log, elfPath, ".dynsym", symbolName, symbolType);
164+
165+
public static bool HasSymbol (IELF elf, string sectionName, string symbolName, ELFSymbolType symbolType = ELFSymbolType.NotSpecified)
166+
{
167+
ISymbolTable? symtab = GetSymbolTable (elf, sectionName);
168+
if (symtab == null) {
169+
return false;
170+
}
171+
172+
foreach (var entry in symtab.Entries) {
173+
if (MonoAndroidHelper.StringEquals (symbolName, entry.Name) && (symbolType == ELFSymbolType.NotSpecified || entry.Type == symbolType)) {
174+
return true;
175+
}
176+
}
177+
178+
return false;
179+
}
180+
181+
public static bool HasPublicSymbol (IELF elf, string symbolName, ELFSymbolType symbolType = ELFSymbolType.NotSpecified) => HasSymbol (elf, ".dynsym", symbolName, symbolType);
182+
183+
public static bool IsJniLibrary (TaskLoggingHelper log, string elfPath) => LibraryHasPublicSymbol (log, elfPath, "JNI_OnLoad", ELFSymbolType.Function);
184+
146185
static bool IsLibraryReference (IStringTable stringTable, IDynamicEntry dynEntry, string referencedLibraryName)
147186
{
148187
if (dynEntry.Tag != DynamicTag.Needed) {
@@ -163,26 +202,12 @@ static bool IsLibraryReference (IStringTable stringTable, IDynamicEntry dynEntry
163202

164203
static bool IsEmptyAOTLibrary (TaskLoggingHelper log, string path, IELF elf)
165204
{
166-
ISymbolTable? symtab = GetSymbolTable (elf, ".dynsym");
167-
if (symtab == null) {
168-
// We can't be sure what the DSO is, play safe
169-
return false;
170-
}
171-
172-
bool mono_aot_file_info_found = false;
173-
foreach (var entry in symtab.Entries) {
174-
if (MonoAndroidHelper.StringEquals ("mono_aot_file_info", entry.Name) && entry.Type == ELFSymbolType.Object) {
175-
mono_aot_file_info_found = true;
176-
break;
177-
}
178-
}
179-
180-
if (!mono_aot_file_info_found) {
205+
if (!HasPublicSymbol (elf, "mono_aot_file_info", ELFSymbolType.Object)) {
181206
// Not a MonoVM AOT assembly
182207
return false;
183208
}
184209

185-
symtab = GetSymbolTable (elf, ".symtab");
210+
ISymbolTable? symtab = GetSymbolTable (elf, ".symtab");
186211
if (symtab == null) {
187212
// The DSO is stripped, we can't tell if there are any functions defined (.text will be present anyway)
188213
// We perhaps **can** take a look at the .text section size, but it's not a solid check...

src/native/clr/include/xamarin-app.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ struct DSOCacheEntry
258258
const uint64_t hash;
259259
const uint64_t real_name_hash;
260260
const bool ignore;
261+
const bool is_jni_library;
261262
const uint32_t name_index;
262263
void *handle;
263264
};

src/native/clr/xamarin-app-stub/application_dso_stub.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ DSOCacheEntry dso_cache[] = {
112112
.hash = xamarin::android::xxhash::hash (fake_dso_name, sizeof(fake_dso_name) - 1),
113113
.real_name_hash = xamarin::android::xxhash::hash (fake_dso_name, sizeof(fake_dso_name) - 1),
114114
.ignore = true,
115+
.is_jni_library = false,
115116
.name_index = 1,
116117
.handle = nullptr,
117118
},
@@ -120,6 +121,7 @@ DSOCacheEntry dso_cache[] = {
120121
.hash = xamarin::android::xxhash::hash (fake_dso_name2, sizeof(fake_dso_name2) - 1),
121122
.real_name_hash = xamarin::android::xxhash::hash (fake_dso_name2, sizeof(fake_dso_name2) - 1),
122123
.ignore = true,
124+
.is_jni_library = false,
123125
.name_index = 2,
124126
.handle = nullptr,
125127
},

src/native/mono/xamarin-app-stub/xamarin-app.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ struct DSOCacheEntry
269269
uint64_t hash;
270270
uint64_t real_name_hash;
271271
bool ignore;
272+
const bool is_jni_library;
272273
const char *name;
273274
void *handle;
274275
};

0 commit comments

Comments
 (0)