1#include <elf.h>
2#include <fcntl.h>
3#include <getopt.h>
4#include <sys/auxv.h>
5#include <sys/mman.h>
6#include <unistd.h>
7
8#include <cassert>
9#include <cstring>
10#include <ctime>
11#include <filesystem>
12#include <fstream>
13#include <iomanip>
14#include <iostream>
15#include <memory>
16#include <string>
17#include <vector>
18
19#include "dyn_loader.h"
20#include "exec_loader.h"
21#include "utils.h"
22
23Elf64_Half GetEType(const std::filesystem::path& filepath) {
24 int fd = open(filepath.c_str(), O_RDONLY);
25 CHECK(fd >= 0);
26
27 size_t size = lseek(fd, 0, SEEK_END);
28 CHECK_GT(size, 8UL + 16UL);
29
30 size_t mapped_size = (size + 0xfff) & ~0xfff;
31
32 char* p = (char*)mmap(NULL, mapped_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
33 LOG(FATAL) << LOG_BITS(mapped_size) << LOG_BITS(size) << LOG_KEY(filepath);
34 CHECK(p != MAP_FAILED);
35
36 Elf64_Ehdr* ehdr = reinterpret_cast<Elf64_Ehdr*>(p);
37 return ehdr->e_type;
38}
39
40int main(int argc, char* const argv[], char** envp) {
41 std::string argv0 = argv[1];
42 std::filesystem::path fullpath;
43
44 if (argv0[0] == '.' || argv0.find("/") != std::string::npos) {
45 fullpath = std::filesystem::path(argv0);
46 } else {
47 std::vector<std::string> path_dirs = SplitWith(std::string(getenv("PATH")), ":");
48 for (const auto& dir : path_dirs) {
49 std::filesystem::path p = std::filesystem::path(dir) / argv0;
50 if (std::filesystem::exists(p) && std::filesystem::is_regular_file(p)) {
51 fullpath = p;
52 break;
53 }
54 }
55 }
56
57 LOG(INFO) << LOG_KEY(fullpath);
58 CHECK(std::filesystem::exists(fullpath));
59
60 std::vector<std::string> args;
61 for (int i = 1; i < argc; i++) {
62 args.emplace_back(argv[i]);
63 }
64
65 std::vector<std::string> envs;
66 for (char** env = envp; *env != 0; env++) {
67 envs.emplace_back(*env);
68 }
69
70 Elf64_Half etype = GetEType(fullpath);
71 if (etype == ET_DYN || etype == ET_EXEC) {
72 InitializeDynLoader(fullpath, envs, args);
73 GetDynLoader()->Run();
74 } else {
75 LOG(FATAL) << "Unsupported etype = " << LOG_KEY(etype);
76 std::abort();
77 }
78}
79