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