Separate PLT lookup
[centaur.git] / src / elfucli.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <getopt.h>
5 #include <libelfu/libelfu.h>
6
7 #include "elfhandle.h"
8
9
10
11 static void printUsage(char *progname)
12 {
13   printf("Usage: %s -i <inputfile> [OPTIONS]\n", progname);
14   printf("\n"
15          "Options, executed in order given:\n"
16          "  -h, --help                     Print this help message\n"
17          "\n"
18          "  -i, --input         infile     Load new ELF file (must be first command)\n"
19          "\n"
20          "  -c, --check                    Do a few sanity checks and print any errors\n"
21          "  -d, --dump                     Dump current model state (debug only)\n"
22          "      --reladd        obj.o      Insert object file contents\n"
23          "      --detour        from,to    Write a jump to <to> at <from>\n"
24          "  -o, --output        outfile    Where to write the modified ELF file to\n"
25          "\n");
26 }
27
28
29
30
31 int main(int argc, char **argv)
32 {
33   ELFHandles hIn = { 0 };
34   int exitval = EXIT_SUCCESS;
35   char *progname = argv[0];
36   int c;
37   int option_index = 0;
38   ElfuElf *me = NULL;
39
40   static struct option long_options[] = {
41     {"help", 0, 0, 'h'},
42     {"check", 0, 0, 'c'},
43     {"dump", 0, 0, 'd'},
44     {"input", 1, 0, 'i'},
45     {"output", 1, 0, 'o'},
46     {"reladd", 1, 0, 10001},
47     {"detour", 1, 0, 10002},
48     {NULL, 0, NULL, 0}
49   };
50
51
52   if (argc < 3) {
53     printUsage(progname);
54     goto EXIT;
55   }
56
57
58   /* Is libelf alive and well? */
59   if (elf_version(EV_CURRENT) == EV_NONE) {
60     fprintf(stderr, "libelf init error: %s\n", elf_errmsg(-1));
61   }
62
63
64   /* Parse and and execute user commands */
65   while ((c = getopt_long(argc, argv, "hcdi:o:",
66                           long_options, &option_index)) != -1) {
67     switch (c) {
68       case 'h':
69         printUsage(progname);
70         goto EXIT;
71       case 'c':
72         if (!me) {
73           goto ERR_NO_INPUT;
74         } else {
75           printf("Checking model validity...\n");
76           elfu_mCheck(me);
77         }
78         break;
79       case 'd':
80         if (!me) {
81           goto ERR_NO_INPUT;
82         } else {
83           elfu_mDumpElf(me);
84         }
85         break;
86       case 'i':
87         if (me) {
88           elfu_mElfDestroy(me);
89         }
90
91         printf("Opening input file %s.\n", optarg);
92         openElf(&hIn, optarg, ELF_C_READ);
93         if (!hIn.e) {
94           printf("Error: Failed to open input file. Aborting.\n");
95           exitval = EXIT_FAILURE;
96           goto EXIT;
97         }
98
99         me = elfu_mFromElf(hIn.e);
100         closeElf(&hIn);
101
102         if (!me) {
103           printf("Error: Failed to load model, aborting.\n");
104           goto EXIT;
105         }
106         break;
107       case 'o':
108         if (!me) {
109           goto ERR_NO_INPUT;
110         } else {
111           ELFHandles hOut = { 0 };
112
113           printf("Writing modified file to %s.\n", optarg);
114
115           openElf(&hOut, optarg, ELF_C_WRITE);
116           if (!hOut.e) {
117             printf("Failed to open output file. Aborting.\n");
118             closeElf(&hOut);
119             exitval = EXIT_FAILURE;
120             goto EXIT;
121           }
122
123           elfu_mToElf(me, hOut.e);
124
125           if (elf_update(hOut.e, ELF_C_WRITE) < 0) {
126             fprintf(stderr, "elf_update() failed: %s\n", elf_errmsg(-1));
127           }
128           closeElf(&hOut);
129         }
130         break;
131       case 10001:
132         if (!me) {
133           goto ERR_NO_INPUT;
134         } else {
135           ELFHandles hRel = { 0 };
136           ElfuElf *mrel = NULL;
137
138           openElf(&hRel, optarg, ELF_C_READ);
139           if (!hRel.e) {
140             printf("--reladd: Failed to open file for --reladd, aborting.\n");
141             closeElf(&hRel);
142             goto ERR;
143           }
144
145           mrel = elfu_mFromElf(hRel.e);
146           closeElf(&hRel);
147           if (!mrel) {
148             printf("--reladd: Failed to load model for --reladd, aborting.\n");
149             goto ERR;
150           } else {
151             printf("--reladd: Injecting %s...\n", optarg);
152             if (elfu_mCheck(mrel)) {
153               printf("--reladd: Check for input file failed.\n");
154               goto ERR;
155             }
156             if (elfu_mReladd(me, mrel)) {
157               printf("--reladd: Failed.\n");
158               goto ERR;
159             }
160             printf("--reladd: Injected %s.\n", optarg);
161           }
162         }
163         break;
164       case 10002:
165         if (!me) {
166           goto ERR_NO_INPUT;
167         } else {
168           GElf_Addr from;
169           GElf_Addr to;
170           char *second;
171
172           strtok_r(optarg, ",", &second);
173           printf("--detour: From '%s' to '%s'\n", optarg, second);
174
175
176           from = strtoul(optarg, NULL, 0);
177           if (from == 0) {
178             from = elfu_mSymtabLookupAddrByName(me, me->symtab, optarg);
179           }
180           if (from == 0) {
181             printf("--detour: Cannot parse argument 1, aborting.\n");
182             goto ERR;
183           }
184           printf("--detour: From %x\n", (unsigned)from);
185
186           to = strtoul(second, NULL, 0);
187           if (to == 0) {
188             to = elfu_mSymtabLookupAddrByName(me, me->symtab, second);
189           }
190           if (to == 0) {
191             printf("--detour: Cannot parse argument 2, aborting.\n");
192             goto ERR;
193           }
194           printf("--detour: To %x\n", (unsigned)to);
195
196           elfu_mDetour(me, from, to);
197         }
198         break;
199       case '?':
200       default:
201         printUsage(progname);
202         goto EXIT;
203     }
204   }
205
206   while (optind < argc) {
207     optind++;
208   }
209
210
211
212 EXIT:
213   if (me) {
214     elfu_mElfDestroy(me);
215   }
216
217   if (hIn.e) {
218     closeElf(&hIn);
219   }
220
221   return (exitval);
222
223
224 ERR_NO_INPUT:
225   printf("Error: No input file opened. Aborting.\n");
226
227 ERR:
228   exitval = EXIT_FAILURE;
229   goto EXIT;
230 }