Skip to content

Commit 4a8ebdc

Browse files
committed
WIP, managed side
1 parent b1eb50a commit 4a8ebdc

File tree

4 files changed

+72
-10
lines changed

4 files changed

+72
-10
lines changed

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

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public override string GetComment (object data, string fieldName)
4343

4444
// Order of fields and their type must correspond *exactly* (with exception of the
4545
// ignored managed members) to that in
46-
// src/monodroid/jni/xamarin-app.hh DSOCacheEntry structure
46+
// src/native/clr/include/xamarin-app.hh DSOCacheEntry structure
4747
[NativeAssemblerStructContextDataProvider (typeof (DSOCacheEntryContextDataProvider))]
4848
sealed class DSOCacheEntry
4949
{
@@ -66,8 +66,29 @@ sealed class DSOCacheEntry
6666
public IntPtr handle = IntPtr.Zero;
6767
}
6868

69+
sealed class DSOApkEntryContextDataProvider : NativeAssemblerStructContextDataProvider
70+
{
71+
public override string GetComment (object data, string fieldName)
72+
{
73+
var dso_apk_entry = EnsureType<DSOApkEntry> (data);
74+
if (MonoAndroidHelper.StringEquals ("name_hash", fieldName)) {
75+
return $" from name: {dso_apk_entry.Name}";
76+
}
77+
78+
return String.Empty;
79+
}
80+
}
81+
82+
// Order of fields and their type must correspond *exactly* (with exception of the
83+
// ignored managed members) to that in
84+
// src/native/clr/include/xamarin-app.hh DSOApkEntry structure
85+
[NativeAssemblerStructContextDataProvider (typeof (DSOApkEntryContextDataProvider))]
6986
sealed class DSOApkEntry
7087
{
88+
[NativeAssembler (Ignore = true)]
89+
public string Name = String.Empty;
90+
91+
[NativeAssembler (UsesDataProvider = true, NumberFormat = LlvmIrVariableNumberFormat.Hexadecimal)]
7192
public ulong name_hash;
7293
public uint offset; // offset into the APK
7394
public int fd; // apk file descriptor
@@ -411,10 +432,9 @@ protected override void Construct (LlvmIrModule module)
411432
module.Add (aot_dso_cache);
412433
module.AddGlobalVariable ("dso_names_data", dsoState.NamesBlob, LlvmIrVariableOptions.GlobalConstant);
413434

414-
var dso_apk_entries = new LlvmIrGlobalVariable (typeof(List<StructureInstance<DSOApkEntry>>), "dso_apk_entries") {
415-
ArrayItemCount = (ulong)NativeLibraries.Count,
435+
var dso_apk_entries = new LlvmIrGlobalVariable (new List<StructureInstance<DSOApkEntry>> (NativeLibraries.Count), "dso_apk_entries") {
416436
Options = LlvmIrVariableOptions.GlobalWritable,
417-
ZeroInitializeArray = true,
437+
BeforeWriteCallback = PopulateDsoApkEntries,
418438
};
419439
module.Add (dso_apk_entries);
420440

@@ -566,16 +586,45 @@ void AddAssemblyStores (LlvmIrModule module)
566586
module.Add (assembly_store);
567587
}
568588

589+
void PopulateDsoApkEntries (LlvmIrVariable variable, LlvmIrModuleTarget target, object? state)
590+
{
591+
var dso_apk_entries = variable.Value as List<StructureInstance<DSOApkEntry>>;
592+
if (dso_apk_entries == null) {
593+
throw new InvalidOperationException ("Internal error: DSO apk entries list not present.");
594+
}
595+
596+
if (dso_apk_entries.Capacity != NativeLibraries.Count) {
597+
throw new InvalidOperationException ($"Internal error: DSO apk entries count ({dso_apk_entries.Count}) is different to the native libraries count ({NativeLibraries.Count}).");
598+
}
599+
600+
bool is64Bit = target.Is64Bit;
601+
foreach (ITaskItem item in NativeLibraries) {
602+
string name = Path.GetFileName (item.ItemSpec);
603+
var entry = new DSOApkEntry {
604+
Name = name,
605+
606+
name_hash = MonoAndroidHelper.GetXxHash (name, is64Bit),
607+
offset = 0,
608+
fd = -1,
609+
};
610+
dso_apk_entries.Add (new StructureInstance<DSOApkEntry> (dsoApkEntryStructureInfo, entry));
611+
}
612+
613+
dso_apk_entries.Sort ((StructureInstance<DSOApkEntry> a, StructureInstance<DSOApkEntry> b) => {
614+
return a.Instance!.name_hash.CompareTo (b.Instance!.name_hash);
615+
});
616+
}
617+
569618
void PopulatePreloadIndices (LlvmIrVariable variable, LlvmIrModuleTarget target, object? state)
570619
{
571620
var indices = variable.Value as List<uint>;
572621
if (indices == null) {
573-
throw new InvalidOperationException ($"Internal error: DSO preload indices list instance not present.");
622+
throw new InvalidOperationException ("Internal error: DSO preload indices list instance not present.");
574623
}
575624

576625
var dsoState = state as DsoCacheState;
577626
if (dsoState == null) {
578-
throw new InvalidOperationException ($"Internal error: DSO state not present.");
627+
throw new InvalidOperationException ("Internal error: DSO state not present.");
579628
}
580629

581630
foreach (DSOCacheEntry preload in dsoState.JniPreloadDSOs) {

src/native/clr/host/host.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <runtime-base/search.hh>
2828
#include <runtime-base/timing-internal.hh>
2929
#include <shared/log_types.hh>
30+
#include <shared/xxhash.hh>
3031
#include <startup/zip.hh>
3132

3233
using namespace xamarin::android;
@@ -145,6 +146,16 @@ auto Host::zip_scan_callback (std::string_view const& apk_path, int apk_fd, dyna
145146
return false; // This will make the scanner keep the APK open
146147
}
147148
}
149+
150+
if (!entry_name.starts_with (Zip::lib_prefix) || !entry_name.ends_with (Constants::dso_suffix)) {
151+
return false;
152+
}
153+
154+
log_debug (LOG_ASSEMBLY, "Found shared library in '{}': {}"sv, apk_path, entry_name.get ());
155+
std::string_view lib_name { entry_name.get () + Zip::lib_prefix.length () };
156+
hash_t name_hash = xxhash::hash (lib_name.data (), lib_name.length ());
157+
log_debug (LOG_ASSEMBLY, "Library name is: {}; hash == 0x{:x}", lib_name, name_hash);
158+
148159
return false;
149160
}
150161

src/native/clr/include/startup/zip.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,11 @@ namespace xamarin::android {
5656
static constexpr size_t lib_prefix_size = calc_size(apk_lib_dir_name, zip_path_separator, Constants::android_lib_abi, zip_path_separator);
5757
static constexpr auto lib_prefix_array = concat_string_views<lib_prefix_size> (apk_lib_dir_name, zip_path_separator, Constants::android_lib_abi, zip_path_separator);
5858

59+
public:
5960
// .data() must be used otherwise string_view length will include the trailing \0 in the array
6061
static constexpr std::string_view lib_prefix { lib_prefix_array.data () };
6162

63+
private:
6264
static constexpr size_t assembly_store_file_path_size = calc_size(lib_prefix, Constants::assembly_store_file_name);
6365
static constexpr auto assembly_store_file_path_array = concat_string_views<assembly_store_file_path_size> (lib_prefix, Constants::assembly_store_file_name);
6466

src/native/common/include/runtime-base/strings.hh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ namespace xamarin::android {
722722
}
723723

724724
[[gnu::always_inline]]
725-
auto starts_with_c (const char* s) noexcept -> bool
725+
auto starts_with_c (const char* s) const noexcept -> bool
726726
{
727727
if (s == nullptr) {
728728
return false;
@@ -732,19 +732,19 @@ namespace xamarin::android {
732732
}
733733

734734
template<size_t Size> [[gnu::always_inline]]
735-
auto starts_with (const char (&s)[Size]) noexcept -> bool
735+
auto starts_with (const char (&s)[Size]) const noexcept -> bool
736736
{
737737
return starts_with (s, Size - 1);
738738
}
739739

740740
[[gnu::always_inline]]
741-
auto starts_with (std::string_view const& s) noexcept -> bool
741+
auto starts_with (std::string_view const& s) const noexcept -> bool
742742
{
743743
return starts_with (s.data (), s.length ());
744744
}
745745

746746
[[gnu::always_inline]]
747-
auto ends_with (std::string_view const& s) noexcept -> bool
747+
auto ends_with (std::string_view const& s) const noexcept -> bool
748748
{
749749
if (empty () || s.length () > buffer.size ()) {
750750
return false;

0 commit comments

Comments
 (0)