1b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines/*
2b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * Copyright 2011, The Android Open Source Project
3b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines *
4b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
5b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * you may not use this file except in compliance with the License.
6b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * You may obtain a copy of the License at
7b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines *
8b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines *     http://www.apache.org/licenses/LICENSE-2.0
9b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines *
10b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * Unless required by applicable law or agreed to in writing, software
11b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
12b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * See the License for the specific language governing permissions and
14b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * limitations under the License.
15b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines */
16b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
17b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include "librsloader.h"
18b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include "utils/rsl_assert.h"
19b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
20b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <stdio.h>
21b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <stdlib.h>
22b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <string.h>
23b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <time.h>
24b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
25b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <fcntl.h>
26b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <sys/mman.h>
27b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <sys/stat.h>
28b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <sys/types.h>
29b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <unistd.h>
30b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
31b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesstruct func_entry_t {
32b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  char const *name;
33b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  size_t name_len;
34b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  void *addr;
35b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines};
36b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
37b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesvoid *find_sym(void *context, char const *name) {
38b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  static struct func_entry_t const tab[] = {
39b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#define DEF(NAME, ADDR) \
40b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    { NAME, sizeof(NAME) - 1, (void *)(&(ADDR)) },
41b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
42b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("printf", printf)
43b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("scanf", scanf)
44b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("__isoc99_scanf", scanf)
45b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("rand", rand)
46b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("time", time)
47b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("srand", srand)
48b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#undef DEF
49b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  };
50b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
51b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t);
52b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
53b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // Note: Since our table is small, we are using trivial O(n) searching
54b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // function.  For bigger table, it will be better to use binary
55b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // search or hash function.
56b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  size_t i;
57b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  size_t name_len = strlen(name);
58b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  for (i = 0; i < tab_size; ++i) {
59b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
60b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines      return tab[i].addr;
61b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    }
62b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
63b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
64b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  rsl_assert(0 && "Can't find symbol.");
65b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  return 0;
66b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
67b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
68b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesint main(int argc, char **argv) {
69b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (argc < 2) {
70b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    fprintf(stderr, "USAGE: %s [ELF] [ARGS]\n", argv[0]);
71b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    exit(EXIT_FAILURE);
72b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
73b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
74b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  int fd = open(argv[1], O_RDONLY);
75b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (fd < 0) {
76b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    fprintf(stderr, "ERROR: Unable to open the file: %s\n", argv[1]);
77b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    exit(EXIT_FAILURE);
78b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
79b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
80b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  struct stat sb;
81b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (fstat(fd, &sb) != 0) {
82b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    fprintf(stderr, "ERROR: Unable to stat the file: %s\n", argv[1]);
83b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    close(fd);
84b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    exit(EXIT_FAILURE);
85b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
86b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
87b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  unsigned char const *image = (unsigned char const *)
88b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
89b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
90b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (image == MAP_FAILED) {
91b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    fprintf(stderr, "ERROR: Unable to mmap the file: %s\n", argv[1]);
92b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    close(fd);
93b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    exit(EXIT_FAILURE);
94b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
95b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
96b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  RSExecRef object = rsloaderCreateExec(image, sb.st_size, find_sym, 0);
97b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (!object) {
98b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    fprintf(stderr, "ERROR: Unable to load elf object.\n");
99b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    close(fd);
100b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    exit(EXIT_FAILURE);
101b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
102b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
103b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  int (*main_stub)(int, char **) =
104b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    (int (*)(int, char **))rsloaderGetSymbolAddress(object, "main");
105b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
106b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  int ret = main_stub(argc - 1, argv + 1);
107b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  printf("============================================================\n");
108b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  printf("ELF object finished with code: %d\n", ret);
109b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  fflush(stdout);
110b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
111b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  rsloaderDisposeExec(object);
112b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
113b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  close(fd);
114b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
115b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  return EXIT_SUCCESS;
116b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
117