1// Copyright 2023 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <dlfcn.h>
6#include <mach-o/dyld.h>
7#include <stdlib.h>
8#include <string.h>
9
10typedef int (*entry_point)(int, char**);
11
12static char kMainRelativePath[] = "/Frameworks/HelloMain.framework/HelloMain";
13
14static char* GetHelloMainPath(void) {
15  uint32_t buffer_size = 0;
16  _NSGetExecutablePath(NULL, &buffer_size);
17  if (buffer_size == 0)
18    return NULL;
19
20  uint32_t suffix_len = sizeof(kMainRelativePath) + 1;
21  if (buffer_size >= UINT32_MAX - suffix_len)
22    return NULL;
23
24  char* buffer = malloc(suffix_len + buffer_size);
25  if (!buffer)
26    return NULL;
27
28  if (_NSGetExecutablePath(buffer, &buffer_size) != 0)
29    return NULL;
30
31  char* last_sep = strrchr(buffer, '/');
32  if (!last_sep)
33    return NULL;
34
35  memcpy(last_sep, kMainRelativePath, suffix_len);
36  return buffer;
37}
38
39int main(int argc, char** argv) {
40  char* hello_main_path = GetHelloMainPath();
41  if (!hello_main_path)
42    return 1;
43
44  void* hello_main_handle = dlopen(hello_main_path, RTLD_NOW);
45  if (!hello_main_handle)
46    return 1;
47
48  free(hello_main_path);
49  hello_main_path = NULL;
50
51  entry_point hello_main_entry = dlsym(hello_main_handle, "hello_main");
52  if (!hello_main_entry)
53    return 1;
54
55  int retcode = hello_main_entry(argc, argv);
56  if (retcode) {
57    return retcode;
58  }
59
60  if (!dlclose(hello_main_handle)) {
61    return 1;
62  }
63
64  return 0;
65}
66