Implement memory management TODOs
[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               elfu_mElfDestroy(mrel);
155               goto ERR;
156             }
157             if (elfu_mReladd(me, mrel)) {
158               printf("--reladd: Failed.\n");
159               elfu_mElfDestroy(mrel);
160               goto ERR;
161             }
162             printf("--reladd: Injected %s.\n", optarg);
163             elfu_mElfDestroy(mrel);
164           }
165         }
166         break;
167       case 10002:
168         if (!me) {
169           goto ERR_NO_INPUT;
170         } else {
171           GElf_Addr from;
172           GElf_Addr to;
173           char *second;
174
175           strtok_r(optarg, ",", &second);
176           printf("--detour: From '%s' to '%s'\n", optarg, second);
177
178
179           from = strtoul(optarg, NULL, 0);
180           if (from == 0) {
181             from = elfu_mSymtabLookupAddrByName(me, me->symtab, optarg);
182           }
183           if (from == 0) {
184             printf("--detour: Cannot parse argument 1, aborting.\n");
185             goto ERR;
186           }
187           printf("--detour: From %x\n", (unsigned)from);
188
189           to = strtoul(second, NULL, 0);
190           if (to == 0) {
191             to = elfu_mSymtabLookupAddrByName(me, me->symtab, second);
192           }
193           if (to == 0) {
194             printf("--detour: Cannot parse argument 2, aborting.\n");
195             goto ERR;
196           }
197           printf("--detour: To %x\n", (unsigned)to);
198
199           elfu_mDetour(me, from, to);
200         }
201         break;
202       case '?':
203       default:
204         printUsage(progname);
205         goto EXIT;
206     }
207   }
208
209   while (optind < argc) {
210     optind++;
211   }
212
213
214
215 EXIT:
216   if (me) {
217     elfu_mElfDestroy(me);
218   }
219
220   if (hIn.e) {
221     closeElf(&hIn);
222   }
223
224   return (exitval);
225
226
227 ERR_NO_INPUT:
228   printf("Error: No input file opened. Aborting.\n");
229
230 ERR:
231   exitval = EXIT_FAILURE;
232   goto EXIT;
233 }