|
11 | 11 | #include <sys/stat.h> |
12 | 12 | #include <dlfcn.h> |
13 | 13 | #include <mach/mach.h> |
| 14 | +#include <mach-o/dyld.h> |
| 15 | +#include <mach-o/loader.h> |
14 | 16 |
|
15 | 17 | #include "product.h" |
16 | 18 | #include "shared.h" |
|
22 | 24 | #include "xamarin/monovm-bridge.h" |
23 | 25 | #else |
24 | 26 | #include "xamarin/coreclr-bridge.h" |
| 27 | +#include "host_runtime_contract.h" |
25 | 28 | #endif |
26 | 29 |
|
27 | 30 | #if defined (DEBUG) |
@@ -2436,37 +2439,149 @@ -(struct NSObjectData*) xamarinGetNSObjectData; |
2436 | 2439 | return rv; |
2437 | 2440 | } |
2438 | 2441 |
|
| 2442 | +#if defined (CORECLR_RUNTIME) |
| 2443 | +size_t get_image_size(void* base_address) |
| 2444 | +{ |
| 2445 | + uint32_t image_count = _dyld_image_count(); |
| 2446 | + for (uint32_t i = 0; i < image_count; ++i) |
| 2447 | + { |
| 2448 | + const struct mach_header_64* header = (const struct mach_header_64*)_dyld_get_image_header(i); |
| 2449 | + if ((const void*)header != base_address) |
| 2450 | + continue; |
| 2451 | + |
| 2452 | + const struct load_command* cmd = (const struct load_command*)((const char*)header + sizeof(struct mach_header_64)); |
| 2453 | + |
| 2454 | + size_t image_size = 0; |
| 2455 | + for (uint32_t j = 0; j < header->ncmds; ++j) |
| 2456 | + { |
| 2457 | + if (cmd->cmd == LC_SEGMENT_64) |
| 2458 | + { |
| 2459 | + const struct segment_command_64* seg = (const struct segment_command_64*)cmd; |
| 2460 | + size_t end_addr = (size_t)(seg->vmaddr + seg->vmsize); |
| 2461 | + if (end_addr > image_size) |
| 2462 | + image_size = end_addr; |
| 2463 | + } |
| 2464 | + |
| 2465 | + cmd = (const struct load_command*)((const char*)cmd + cmd->cmdsize); |
| 2466 | + } |
| 2467 | + |
| 2468 | + return image_size; |
| 2469 | + } |
| 2470 | + |
| 2471 | + return 0; |
| 2472 | +} |
| 2473 | + |
| 2474 | +bool get_native_code_data(const struct host_runtime_contract_native_code_context* context, struct host_runtime_contract_native_code_data* data) |
| 2475 | +{ |
| 2476 | + // TODO: Remove fprintf logs |
| 2477 | + fprintf (stderr, "R2R: get_native_code_data called for assembly: %s, composite: %s\n", |
| 2478 | + context ? context->assembly_path : "(null)", |
| 2479 | + context ? context->owner_composite_name : "(null)"); |
| 2480 | + |
| 2481 | + if (!context || !data || !context->assembly_path || !context->owner_composite_name) |
| 2482 | + return false; |
| 2483 | + |
| 2484 | + // Look for the owner composite R2R image in the same directory as the assembly |
| 2485 | + char r2r_path[PATH_MAX]; |
| 2486 | + const char *last_slash = strrchr(context->assembly_path, '/'); |
| 2487 | + size_t dir_len = last_slash ? (size_t)(last_slash - context->assembly_path) : 0; |
| 2488 | + if (dir_len >= sizeof(r2r_path) - 1) |
| 2489 | + return false; |
| 2490 | + |
| 2491 | + strncpy(r2r_path, context->assembly_path, dir_len); |
| 2492 | + int written = snprintf(r2r_path + dir_len, sizeof(r2r_path) - dir_len, "/%s", context->owner_composite_name); |
| 2493 | + if (written <= 0 || (size_t)written >= sizeof(r2r_path) - dir_len) |
| 2494 | + return false; |
| 2495 | + |
| 2496 | + fprintf (stderr, "R2R: Attempting to load R2R image from: %s\n", r2r_path); |
| 2497 | + |
| 2498 | + void* handle = dlopen(r2r_path, RTLD_LAZY | RTLD_LOCAL); |
| 2499 | + if (handle == NULL) { |
| 2500 | + fprintf (stderr, "R2R: Failed to dlopen R2R image: %s\n", dlerror ()); |
| 2501 | + return false; |
| 2502 | + } |
| 2503 | + |
| 2504 | + fprintf (stderr, "R2R: Successfully loaded R2R image, looking for RTR_HEADER symbol\n"); |
| 2505 | + |
| 2506 | + void* r2r_header = dlsym(handle, "RTR_HEADER"); |
| 2507 | + if (r2r_header == NULL) |
| 2508 | + { |
| 2509 | + fprintf (stderr, "R2R: Failed to find RTR_HEADER symbol: %s\n", dlerror ()); |
| 2510 | + dlclose(handle); |
| 2511 | + return false; |
| 2512 | + } |
| 2513 | + |
| 2514 | + fprintf (stderr, "R2R: Found RTR_HEADER at %p\n", r2r_header); |
| 2515 | + |
| 2516 | + Dl_info info; |
| 2517 | + if (dladdr(r2r_header, &info) == 0) |
| 2518 | + { |
| 2519 | + fprintf (stderr, "R2R: Failed to get dladdr info for RTR_HEADER\n"); |
| 2520 | + dlclose(handle); |
| 2521 | + return false; |
| 2522 | + } |
| 2523 | + |
| 2524 | + data->size = sizeof(struct host_runtime_contract_native_code_data); |
| 2525 | + data->r2r_header_ptr = r2r_header; |
| 2526 | + data->image_size = get_image_size(info.dli_fbase); |
| 2527 | + data->image_base = info.dli_fbase; |
| 2528 | + |
| 2529 | + fprintf (stderr, "R2R: Successfully loaded R2R data - header: %p, base: %p, size: %lu\n", |
| 2530 | + data->r2r_header_ptr, data->image_base, (unsigned long)data->image_size); |
| 2531 | + |
| 2532 | + return true; |
| 2533 | +} |
| 2534 | +#endif // defined (CORECLR_RUNTIME) |
| 2535 | + |
2439 | 2536 | void |
2440 | 2537 | xamarin_vm_initialize () |
2441 | 2538 | { |
| 2539 | +#if defined (CORECLR_RUNTIME) |
| 2540 | + struct host_runtime_contract host_contract = { |
| 2541 | + .size = sizeof(struct host_runtime_contract), |
| 2542 | + .pinvoke_override = &xamarin_pinvoke_override, |
| 2543 | + .get_native_code_data = &get_native_code_data |
| 2544 | + }; |
| 2545 | + |
| 2546 | + char contract_str[19]; // 0x + 16 hex digits + '\0' |
| 2547 | + snprintf(contract_str, 19, "0x%zx", (size_t)(&host_contract)); |
| 2548 | +#else |
2442 | 2549 | char *pinvokeOverride = xamarin_strdup_printf ("%p", &xamarin_pinvoke_override); |
| 2550 | +#endif |
| 2551 | + |
2443 | 2552 | char *trusted_platform_assemblies = xamarin_compute_trusted_platform_assemblies (); |
2444 | 2553 | char *native_dll_search_directories = xamarin_compute_native_dll_search_directories (); |
2445 | 2554 |
|
2446 | 2555 | // All the properties we pass here must also be listed in the _RuntimeConfigReservedProperties item group |
2447 | 2556 | // for the _CreateRuntimeConfiguration target in dotnet/targets/Xamarin.Shared.Sdk.targets. |
2448 | 2557 | const char *propertyKeys[] = { |
2449 | 2558 | "APP_CONTEXT_BASE_DIRECTORY", // path to where the managed assemblies are (usually at least - RID-specific assemblies will be in subfolders) |
2450 | | - "APP_PATHS", |
| 2559 | +#if defined (CORECLR_RUNTIME) |
| 2560 | + "HOST_RUNTIME_CONTRACT", |
| 2561 | +#else |
2451 | 2562 | "PINVOKE_OVERRIDE", |
| 2563 | +#endif |
2452 | 2564 | "TRUSTED_PLATFORM_ASSEMBLIES", |
2453 | | - "NATIVE_DLL_SEARCH_DIRECTORIES", |
2454 | 2565 | "RUNTIME_IDENTIFIER", |
2455 | 2566 | }; |
2456 | 2567 | const char *propertyValues[] = { |
2457 | 2568 | xamarin_get_bundle_path (), |
2458 | | - xamarin_get_bundle_path (), |
| 2569 | +#if defined (CORECLR_RUNTIME) |
| 2570 | + contract_str, |
| 2571 | +#else |
2459 | 2572 | pinvokeOverride, |
| 2573 | +#endif |
2460 | 2574 | trusted_platform_assemblies, |
2461 | | - native_dll_search_directories, |
2462 | 2575 | RUNTIMEIDENTIFIER, |
2463 | 2576 | }; |
2464 | 2577 | static_assert (sizeof (propertyKeys) == sizeof (propertyValues), "The number of keys and values must be the same."); |
2465 | 2578 |
|
2466 | 2579 | int propertyCount = (int) (sizeof (propertyValues) / sizeof (propertyValues [0])); |
2467 | 2580 | bool rv = xamarin_bridge_vm_initialize (propertyCount, propertyKeys, propertyValues); |
2468 | 2581 |
|
| 2582 | +#if !defined (CORECLR_RUNTIME) |
2469 | 2583 | xamarin_free (pinvokeOverride); |
| 2584 | +#endif |
2470 | 2585 | xamarin_free (trusted_platform_assemblies); |
2471 | 2586 | xamarin_free (native_dll_search_directories); |
2472 | 2587 |
|
@@ -2502,7 +2617,7 @@ -(struct NSObjectData*) xamarinGetNSObjectData; |
2502 | 2617 | return rv; |
2503 | 2618 | } |
2504 | 2619 |
|
2505 | | -void* |
| 2620 | +const void* |
2506 | 2621 | xamarin_pinvoke_override (const char *libraryName, const char *entrypointName) |
2507 | 2622 | { |
2508 | 2623 |
|
|
0 commit comments