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 | |
23 | Elf64_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 | |
40 | int 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 | |