@@ -162,26 +162,35 @@ EmbeddedAssemblies::binary_search (const Key *key, const Entry *base, size_t nme
162
162
MonoReflectionType*
163
163
EmbeddedAssemblies::typemap_java_to_managed (MonoString *java_type)
164
164
{
165
- // #if defined (DEBUG) || !defined (ANDROID)
166
- // for (TypeMappingInfo *info = java_to_managed_maps; info != nullptr; info = info->next) {
167
- // /* log_warn (LOG_DEFAULT, "# jonp: checking file: %s!%s for type '%s'", info->source_apk, info->source_entry, java); */
168
- // const char *e = reinterpret_cast<const char*> (bsearch (java, info->mapping, static_cast<size_t>(info->num_entries), static_cast<size_t>(info->entry_length), TypeMappingInfo_compare_key));
169
- // if (e == nullptr)
170
- // continue;
171
- // return e + info->value_offset;
172
- // }
173
- // #endif
174
165
timing_period total_time;
175
166
if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) {
176
167
timing = new Timing ();
177
168
total_time.mark_start ();
178
169
}
179
170
180
171
simple_pointer_guard<char [], false > java_type_name (mono_string_to_utf8 (java_type));
181
- if (!java_type_name || *java_type_name == ' \0 ' ) {
172
+ if (XA_UNLIKELY (!java_type_name || *java_type_name == ' \0 ' )) {
173
+ return nullptr ;
174
+ }
175
+
176
+ int32_t type_token_id = -1 ;
177
+ #if defined (DEBUG) || !defined (ANDROID)
178
+ size_t idx = 0 ;
179
+ for (; idx < module_count; idx++) {
180
+ const uint8_t *java_entry = binary_search<const char , uint8_t , compare_java_name, true > (java_type_name.get (), modules[idx].java_map , modules[idx].entry_count , modules[idx].java_name_width + 3 );
181
+ if (java_entry == nullptr )
182
+ continue ;
183
+ type_token_id = *reinterpret_cast <const int32_t *>(java_entry + modules[idx].java_name_width );
184
+ break ;
185
+ }
186
+
187
+ if (idx >= module_count) {
188
+ log_error (LOG_ASSEMBLY, " Unable to find module with Java type '%s' mapping" , java_type_name.get ());
182
189
return nullptr ;
183
190
}
184
191
192
+ TypeMapModule &module = modules[idx];
193
+ #else
185
194
const TypeMapJava *java_entry = binary_search<const char , TypeMapJava, compare_java_name, true > (java_type_name.get (), map_java, java_type_count, java_name_width);
186
195
if (java_entry == nullptr ) {
187
196
log_warn (LOG_ASSEMBLY, " Unable to find mapping to a managed type from Java type '%s'" , java_type_name.get ());
@@ -199,6 +208,8 @@ EmbeddedAssemblies::typemap_java_to_managed (MonoString *java_type)
199
208
log_warn (LOG_ASSEMBLY, " Unable to find mapping from Java type '%s' to managed type with token ID %u in module [%s]" , java_type_name.get (), java_entry->type_token_id , mono_guid_to_string (module .module_uuid ));
200
209
return nullptr ;
201
210
}
211
+ type_token_id = java_entry->type_token_id ;
212
+ #endif
202
213
203
214
if (module .image == nullptr ) {
204
215
module .image = mono_image_loaded (module .assembly_name );
@@ -213,10 +224,10 @@ EmbeddedAssemblies::typemap_java_to_managed (MonoString *java_type)
213
224
}
214
225
}
215
226
216
- log_warn (LOG_ASSEMBLY, " Java type '%s' corresponds to managed token id %u (0x%x)" , java_type_name.get (), java_entry-> type_token_id , java_entry-> type_token_id );
217
- MonoClass *klass = mono_class_get (module .image , static_cast <uint32_t >(java_entry-> type_token_id ));
227
+ log_warn (LOG_ASSEMBLY, " Java type '%s' corresponds to managed token id %u (0x%x)" , java_type_name.get (), type_token_id, type_token_id);
228
+ MonoClass *klass = mono_class_get (module .image , static_cast <uint32_t >(type_token_id));
218
229
if (klass == nullptr ) {
219
- log_error (LOG_ASSEMBLY, " Unable to find managed type with token ID %u in assembly '%s', corresponding to Java type '%s'" , java_entry-> type_token_id , module .assembly_name , java_type_name.get ());
230
+ log_error (LOG_ASSEMBLY, " Unable to find managed type with token ID %u in assembly '%s', corresponding to Java type '%s'" , type_token_id, module .assembly_name , java_type_name.get ());
220
231
return nullptr ;
221
232
}
222
233
@@ -236,6 +247,14 @@ EmbeddedAssemblies::compare_java_name (const char *java_name, const TypeMapJava
236
247
return strcmp (java_name, reinterpret_cast <const char *>(entry->java_name ));
237
248
}
238
249
250
+ #if defined (DEBUG) || !defined (ANDROID)
251
+ int
252
+ EmbeddedAssemblies::compare_java_name (const char *java_name, const uint8_t *entry)
253
+ {
254
+ return strcmp (java_name, reinterpret_cast <const char *>(entry));
255
+ }
256
+ #endif // DEBUG || !ANDROID
257
+
239
258
const char *
240
259
EmbeddedAssemblies::typemap_managed_to_java (const uint8_t *mvid, const int32_t token)
241
260
{
@@ -258,7 +277,16 @@ EmbeddedAssemblies::typemap_managed_to_java (const uint8_t *mvid, const int32_t
258
277
return nullptr ;
259
278
}
260
279
261
- const TypeMapModule *match = binary_search<uint8_t , TypeMapModule, compare_mvid> (mvid, map_modules, map_module_count);
280
+ TypeMapModule *map;
281
+ uint32_t map_entry_count;
282
+ #if defined (DEBUG) || !defined (ANDROID)
283
+ map = modules;
284
+ map_entry_count = module_count;
285
+ #else
286
+ map = map_modules;
287
+ map_entry_count = map_module_count;
288
+ #endif
289
+ const TypeMapModule *match = binary_search<uint8_t , TypeMapModule, compare_mvid> (mvid, map, map_entry_count);
262
290
if (match == nullptr ) {
263
291
log_warn (LOG_ASSEMBLY, " Module matching MVID [%s] not found." , mono_guid_to_string (mvid));
264
292
return nullptr ;
@@ -272,17 +300,28 @@ EmbeddedAssemblies::typemap_managed_to_java (const uint8_t *mvid, const int32_t
272
300
// Each map entry is a pair of 32-bit integers: [TypeTokenID][JavaMapArrayIndex]
273
301
const TypeMapModuleEntry *entry = binary_search <int32_t , TypeMapModuleEntry, compare_type_token> (&token, match->map , match->entry_count );
274
302
if (entry == nullptr ) {
275
- log_warn (LOG_ASSEMBLY, " Type with token %d in module [%s] not found." , token, mono_guid_to_string (mvid));
303
+ log_warn (LOG_ASSEMBLY, " Type with token %d (0x%x) in module {%s} (%s) not found." , token, token, mono_guid_to_string (mvid), match-> assembly_name );
276
304
return nullptr ;
277
305
}
278
306
279
- if (entry->java_map_index >= java_type_count) {
280
- log_warn (LOG_ASSEMBLY, " Type with token %d in module [%s] has invalid Java type index %u" , token, mono_guid_to_string (mvid), entry->java_map_index );
307
+ uint32_t java_entry_count;
308
+ #if defined (DEBUG) || !defined (ANDROID)
309
+ java_entry_count = match->entry_count ;
310
+ #else
311
+ java_entry_count = java_type_count;
312
+ #endif
313
+ if (entry->java_map_index >= java_entry_count) {
314
+ log_warn (LOG_ASSEMBLY, " Type with token %d (0x%x) in module {%s} (%s) has invalid Java type index %u" , token, token, mono_guid_to_string (mvid), match->assembly_name , entry->java_map_index );
281
315
return nullptr ;
282
316
}
283
317
318
+ char *ret;
319
+ #if defined (DEBUG) || !defined (ANDROID)
320
+ ret = reinterpret_cast <char *>(match->java_map + ((match->java_name_width + 4 ) * entry->java_map_index ));
321
+ #else
284
322
const TypeMapJava *java_entry = reinterpret_cast <const TypeMapJava*> (reinterpret_cast <const uint8_t *>(map_java) + ((sizeof (TypeMapJava) + java_name_width) * entry->java_map_index ));
285
- const char *ret = reinterpret_cast <const char *>(java_entry->java_name );
323
+ ret = reinterpret_cast <char *>(java_entry->java_name );
324
+ #endif
286
325
287
326
if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) {
288
327
total_time.mark_end ();
@@ -292,9 +331,11 @@ EmbeddedAssemblies::typemap_managed_to_java (const uint8_t *mvid, const int32_t
292
331
293
332
log_debug (
294
333
LOG_ASSEMBLY,
295
- " Type with token %d in module [%s] corresponds to Java type '%s'" ,
334
+ " Type with token %d (0x%x) in module {%s} (%s) corresponds to Java type '%s'" ,
335
+ token,
296
336
token,
297
337
mono_guid_to_string (mvid),
338
+ match->assembly_name ,
298
339
ret
299
340
);
300
341
@@ -482,11 +523,10 @@ EmbeddedAssemblies::typemap_read_header ([[maybe_unused]] int dir_fd, const char
482
523
return false ;
483
524
}
484
525
485
- size_t data_size = 0 ;
486
526
ssize_t nread = read (fd, &header, sizeof (header));
487
527
if (nread <= 0 ) {
488
528
if (nread < 0 ) {
489
- log_error (LOG_ASSEMBLY, " Failed to read %s file header from '%s/%s': %s" , file_type, dir_path, file_path, strerror (errno));
529
+ log_error (LOG_ASSEMBLY, " Failed to read %s file header from '%s/%s': %s" , file_type, dir_path, file_path, strerror (errno));
490
530
} else {
491
531
log_error (LOG_ASSEMBLY, " End of file while reading %s file header from '%s/%s'" , file_type, dir_path, file_path);
492
532
}
@@ -507,31 +547,58 @@ EmbeddedAssemblies::typemap_read_header ([[maybe_unused]] int dir_fd, const char
507
547
return true ;
508
548
}
509
549
510
- bool
550
+ uint8_t *
551
+ EmbeddedAssemblies::typemap_load_index (TypeMapIndexHeader &header, size_t file_size, int index_fd)
552
+ {
553
+ constexpr size_t UUID_SIZE = 16 ;
554
+
555
+ size_t entry_size = header.module_file_name_width + UUID_SIZE;
556
+ size_t data_size = entry_size * module_count;
557
+ if (sizeof (header) + data_size > file_size) {
558
+ log_error (LOG_ASSEMBLY, " Index file is too small, expected %u, found %u bytes" , data_size + sizeof (header), file_size);
559
+ return nullptr ;
560
+ }
561
+
562
+ auto data = new uint8_t [data_size];
563
+ ssize_t nread = read (index_fd, data, data_size);
564
+ if (nread != static_cast <ssize_t >(data_size)) {
565
+ log_error (LOG_ASSEMBLY, " Failed to read %u bytes from index file. %s" , data_size, strerror (errno));
566
+ return nullptr ;
567
+ }
568
+
569
+ uint8_t *p = data;
570
+ for (size_t i = 0 ; i < module_count; i++) {
571
+ memcpy (modules[i].module_uuid , p, UUID_SIZE);
572
+ modules[i].assembly_name = reinterpret_cast <char *>(p + UUID_SIZE);
573
+ p += entry_size;
574
+ }
575
+
576
+ return data;
577
+ }
578
+
579
+ uint8_t *
511
580
EmbeddedAssemblies::typemap_load_index (int dir_fd, const char *dir_path, const char *index_path)
512
581
{
513
582
log_debug (LOG_ASSEMBLY, " Loading TypeMap index file '%s/%s'" , dir_path, index_path);
514
583
515
- bool ret = true ;
516
584
TypeMapIndexHeader header;
517
585
size_t file_size;
518
586
int fd = -1 ;
587
+ uint8_t *data = nullptr ;
519
588
520
589
if (!typemap_read_header (dir_fd, " TypeMap index" , dir_path, index_path, MODULE_INDEX_MAGIC, header, file_size, fd)) {
521
- ret = false ;
522
590
goto cleanup;
523
591
}
524
592
525
593
module_count = header.entry_count ;
526
- modules = new TypeMapModule[module_count];
527
- // TODO: read actual data
528
- // TODO: pre-fill UUID + file name (store in `assembly_name`) from the previous step
594
+ modules = new TypeMapModule[module_count]();
595
+ data = typemap_load_index (header, file_size, fd);
529
596
530
597
cleanup:
531
598
if (fd >= 0 )
532
599
close (fd);
533
600
534
- return ret ;
601
+ return data ;
535
602
}
536
603
537
604
bool
@@ -543,17 +610,66 @@ EmbeddedAssemblies::typemap_load_file (int dir_fd, const char *dir_path, const c
543
610
BinaryTypeMapHeader header;
544
611
size_t file_size;
545
612
int fd = -1 ;
613
+ size_t alloc_size;
614
+ ssize_t nread;;
615
+ char *chars;
616
+ uint8_t *p;
546
617
547
618
if (!typemap_read_header (dir_fd, " TypeMap" , dir_path, file_path, MODULE_MAGIC, header, file_size, fd)) {
548
619
ret = false ;
549
620
goto cleanup;
550
621
}
551
622
552
- log_debug (LOG_ASSEMBLY, " TypeMap '%s/%s': entry count == %u; Java type name field width == %u; MVID == %s" , dir_path, file_path, header.entry_count , header.java_name_width , mono_guid_to_string (header.module_uuid ));
553
-
623
+ alloc_size = ADD_WITH_OVERFLOW_CHECK (size_t , header.assembly_name_length , 1 );
624
+ module .assembly_name = new char [alloc_size];
625
+ nread = read (fd, module .assembly_name , header.assembly_name_length );
626
+ module .assembly_name [header.assembly_name_length ] = 0 ;
554
627
module .entry_count = header.entry_count ;
555
- // TODO: set module.assembly_name
556
- // TODO: allocate memory for module.map and read data into it
628
+
629
+ log_debug (LOG_ASSEMBLY, " TypeMap '%s/%s': entry count == %u; Java type name field width == %u; MVID == %s; assembly name length == %u; assembly name == %s" ,
630
+ dir_path, file_path, header.entry_count , header.java_name_width , mono_guid_to_string (header.module_uuid ), header.assembly_name_length , module .assembly_name );
631
+
632
+ alloc_size = MULTIPLY_WITH_OVERFLOW_CHECK (size_t , header.java_name_width + 4 , header.entry_count );
633
+ module .java_name_width = header.java_name_width ;
634
+ module .java_map = new uint8_t [alloc_size];
635
+ nread = read (fd, module .java_map , alloc_size);
636
+ if (nread != static_cast <ssize_t >(alloc_size)) {
637
+ log_error (LOG_ASSEMBLY, " Failed to read %u bytes (java-to-managed) from module file %s/%s. %s" , alloc_size, dir_path, file_path, strerror (errno));
638
+ ret = false ;
639
+ delete[] module .java_map ;
640
+ module .java_map = nullptr ;
641
+ goto cleanup;
642
+ }
643
+
644
+ module .map = new TypeMapModuleEntry[header.entry_count ];
645
+ alloc_size = MULTIPLY_WITH_OVERFLOW_CHECK (size_t , sizeof (TypeMapModuleEntry), header.entry_count );
646
+ nread = read (fd, module .map , alloc_size);
647
+ if (nread != static_cast <ssize_t >(alloc_size)) {
648
+ log_error (LOG_ASSEMBLY, " Failed to read %u bytes (managed-to-java) from module file %s/%s. %s" , alloc_size, dir_path, file_path, strerror (errno));
649
+ ret = false ;
650
+ delete[] module .java_map ;
651
+ module .java_map = nullptr ;
652
+ delete[] module .map ;
653
+ module .map = nullptr ;
654
+ goto cleanup;
655
+ }
656
+
657
+ alloc_size = module .java_name_width + 1 ;
658
+ chars = new char [alloc_size]();
659
+ p = module .java_map ;
660
+ log_debug (LOG_ASSEMBLY, " Java entries in %s/%s" , dir_path, file_path);
661
+ for (size_t i = 0 ; i < module .entry_count ; i++) {
662
+ memcpy (chars, p, module .java_name_width );
663
+ uint32_t token = *reinterpret_cast <const uint32_t *>(p + module .java_name_width );
664
+ log_debug (LOG_ASSEMBLY, " %04u: %s; %u (0x%x)" , i, chars, token, token);
665
+ p += module .java_name_width + 4 ;
666
+ }
667
+ delete[] chars;
668
+
669
+ log_debug (LOG_ASSEMBLY, " Managed entries in %s/%s" , dir_path, file_path);
670
+ for (size_t i = 0 ; i < module .entry_count ; i++) {
671
+ log_debug (LOG_ASSEMBLY, " %04u: token %u (0x%x); index %u" , i, module .map [i].type_token_id , module .map [i].type_token_id , module .map [i].java_map_index );
672
+ }
557
673
558
674
cleanup:
559
675
if (fd >= 0 )
@@ -580,7 +696,11 @@ EmbeddedAssemblies::try_load_typemaps_from_directory (const char *path)
580
696
#endif
581
697
582
698
constexpr char index_name[] = " typemap.index" ;
583
- if (!typemap_load_index (dir_fd, dir_path, index_name)) {
699
+
700
+ // The pointer must be stored here because, after index is loaded, module.assembly_name points into the index data
701
+ // and must be valid until after the actual module file is loaded.
702
+ simple_pointer_guard<uint8_t [], true > index_data = typemap_load_index (dir_fd, dir_path, index_name);
703
+ if (!index_data) {
584
704
log_fatal (LOG_ASSEMBLY, " Unable to load TypeMap data index from '%s/%s'" , dir_path.get (), index_name);
585
705
exit (FATAL_EXIT_NO_ASSEMBLIES); // TODO: use a new error code here
586
706
}
0 commit comments