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 "ELFObject.h"
18b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
19b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include "utils/serialize.h"
20b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include "ELF.h"
21b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
22b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <fcntl.h>
23b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <stdlib.h>
24b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <sys/mman.h>
25b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <sys/stat.h>
26b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <sys/types.h>
27b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <map>
28b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <stdio.h>
29b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <stdarg.h>
30b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
31b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesusing namespace std;
32b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
33b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesbool open_mmap_file(char const *filename,
34b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                    int &fd,
35b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                    unsigned char const *&image,
36b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                    size_t &size);
37b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
38b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesvoid close_mmap_file(int fd,
39b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                     unsigned char const *image,
40b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                     size_t size);
41b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
42b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesvoid dump_and_run_file(unsigned char const *image, size_t size,
43b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                       int argc, char **argv);
44b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
45b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesint main(int argc, char **argv) {
46b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // Check arguments
47b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (argc < 2) {
48b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    llvm::errs() << "USAGE: " << argv[0] << " [ELFObjectFile] [ARGS]\n";
49b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    exit(EXIT_FAILURE);
50b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
51b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
52b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // Filename from argument
53b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  char const *filename = argv[1];
54b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
55b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // Open the file
56b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  int fd = -1;
57b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  unsigned char const *image = NULL;
58b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  size_t image_size = 0;
59b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
60b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (!open_mmap_file(filename, fd, image, image_size)) {
61b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    exit(EXIT_FAILURE);
62b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
63b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
64b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // Dump and run the file
65b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  dump_and_run_file(image, image_size, argc - 1, argv + 1);
66b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
67b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // Close the file
68b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  close_mmap_file(fd, image, image_size);
69b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
70b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  return EXIT_SUCCESS;
71b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
72b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
73b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines// FIXME: I don't like these stub as well.  However, before we implement
74b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines// x86 64bit far jump stub, we have to ensure find_sym only returns
75b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines// near address.
76b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
77b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesint stub_printf(char const *fmt, ...) {
78b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  va_list ap;
79b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  va_start(ap, fmt);
80b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  int result = vprintf(fmt, ap);
81b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  va_end(ap);
82b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  return result;
83b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
84b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
85b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesint stub_scanf(char const *fmt, ...) {
86b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  va_list ap;
87b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  va_start(ap, fmt);
88b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  int result = vscanf(fmt, ap);
89b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  va_end(ap);
90b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  return result;
91b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
92b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
93b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesvoid stub_srand(unsigned int seed) {
94b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  srand(seed);
95b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
96b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
97b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesint stub_rand() {
98b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  return rand();
99b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
100b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
101b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinestime_t stub_time(time_t *output) {
102b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  return time(output);
103b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
104b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
105b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesvoid *find_sym(void *context, char const *name) {
106b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  struct func_entry_t {
107b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    char const *name;
108b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    size_t name_len;
109b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    void *addr;
110b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  };
111b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
112b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  static func_entry_t const tab[] = {
113b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#define DEF(NAME, ADDR) \
114b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    { NAME, sizeof(NAME) - 1, (void *)(ADDR) },
115b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
116b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("printf", stub_printf)
117b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("scanf", stub_scanf)
118b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("__isoc99_scanf", stub_scanf)
119b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("rand", stub_rand)
120b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("time", stub_time)
121b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    DEF("srand", stub_srand)
122b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#undef DEF
123b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  };
124b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
125b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  static size_t const tab_size = sizeof(tab) / sizeof(func_entry_t);
126b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
127b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // Note: Since our table is small, we are using trivial O(n) searching
128b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // function.  For bigger table, it will be better to use binary
129b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // search or hash function.
130b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  size_t name_len = strlen(name);
131b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  for (size_t i = 0; i < tab_size; ++i) {
132b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
133b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines      return tab[i].addr;
134b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    }
135b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
136b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
137b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  assert(0 && "Can't find symbol.");
138b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  return 0;
139b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
140b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
141b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinestemplate <unsigned Bitwidth, typename Archiver>
142b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesvoid dump_and_run_object(Archiver &AR, int argc, char **argv) {
143d282991c78d1fd79a222c5f114e623da255ba8a0Stephen Hines  std::unique_ptr<ELFObject<Bitwidth> > object(ELFObject<Bitwidth>::read(AR));
144b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
145b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (!object) {
146b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    llvm::errs() << "ERROR: Unable to load object\n";
147b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
148b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
149b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  object->print();
150b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  out().flush();
151b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
152b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  ELFSectionSymTab<Bitwidth> *symtab =
153b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    static_cast<ELFSectionSymTab<Bitwidth> *>(
154b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines        object->getSectionByName(".symtab"));
155b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
156b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  object->relocate(find_sym, 0);
157b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  out() << "relocate finished!\n";
158b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  out().flush();
159b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
160b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  int machine = object->getHeader()->getMachine();
161b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
162b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  void *main_addr = symtab->getByName("main")->getAddress(machine);
163b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  out() << "main address: " << main_addr << "\n";
164b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  out().flush();
165b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
166b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  ((int (*)(int, char **))main_addr)(argc, argv);
167b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  fflush(stdout);
168b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
169b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
170b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinestemplate <typename Archiver>
171b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesvoid dump_and_run_file_from_archive(bool is32bit, Archiver &AR,
172b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                                    int argc, char **argv) {
173b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (is32bit) {
174b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    dump_and_run_object<32>(AR, argc, argv);
175b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  } else {
176b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    dump_and_run_object<64>(AR, argc, argv);
177b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
178b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
179b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
180b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesvoid dump_and_run_file(unsigned char const *image, size_t size,
181b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                       int argc, char **argv) {
182b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (size < EI_NIDENT) {
183b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    llvm::errs() << "ERROR: ELF identification corrupted.\n";
184b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    return;
185b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
186b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
187b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (image[EI_DATA] != ELFDATA2LSB && image[EI_DATA] != ELFDATA2MSB) {
188b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    llvm::errs() << "ERROR: Unknown endianness.\n";
189b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    return;
190b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
191b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
192b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (image[EI_CLASS] != ELFCLASS32 && image[EI_CLASS] != ELFCLASS64) {
193b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    llvm::errs() << "ERROR: Unknown machine class.\n";
194b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    return;
195b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
196b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
197b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  bool isLittleEndian = (image[EI_DATA] == ELFDATA2LSB);
198b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  bool is32bit = (image[EI_CLASS] == ELFCLASS32);
199b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
200b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (isLittleEndian) {
201b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    ArchiveReaderLE AR(image, size);
202b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    dump_and_run_file_from_archive(is32bit, AR, argc, argv);
203b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  } else {
204b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    ArchiveReaderBE AR(image, size);
205b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    dump_and_run_file_from_archive(is32bit, AR, argc, argv);
206b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
207b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
208b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
209b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesbool open_mmap_file(char const *filename,
210b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                    int &fd,
211b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                    unsigned char const *&image,
212b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                    size_t &size) {
213b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // Query the file status
214b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  struct stat sb;
215b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (stat(filename, &sb) != 0) {
216b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    llvm::errs() << "ERROR: " << filename << " not found.\n";
217b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    return false;
218b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
219b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
220b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (!S_ISREG(sb.st_mode)) {
221b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    llvm::errs() << "ERROR: " << filename << " is not a regular file.\n";
222b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    return false;
223b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
224b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
225b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  size = (size_t)sb.st_size;
226b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
227b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // Open the file in readonly mode
228b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  fd = open(filename, O_RDONLY);
229b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (fd < 0) {
230b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    llvm::errs() << "ERROR: Unable to open " << filename << "\n";
231b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    return false;
232b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
233b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
234b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  // Map the file image
235b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  image = static_cast<unsigned char const *>(
236b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0));
237b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
238b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (image == MAP_FAILED) {
239b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    llvm::errs() << "ERROR: Unable to map " << filename << " to memory.\n";
240b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    close(fd);
241b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    return false;
242b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
243b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
244b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  return true;
245b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
246b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
247b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesvoid close_mmap_file(int fd,
248b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                     unsigned char const *image,
249b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines                     size_t size) {
250b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (image) {
251b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    munmap((void *)image, size);
252b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
253b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
254b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  if (fd >= 0) {
255b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    close(fd);
256b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
257b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
258