Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: src/untrusted/irt/tls_edit.c

Issue 140653005: Adds tls_edit utility which patches irt_core.nexe's TLS usage. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: gyp builds with host toolsets should not inherit target flags for arm and mips Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #include <errno.h>
Roland McGrath 2014/01/24 18:50:49 Needs copyright header at top.
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <sys/stat.h>
6
7 #include "native_client/src/include/elf32.h"
8 #include "native_client/src/include/elf64.h"
9 #include "native_client/src/include/arm_sandbox.h"
10 #include "native_client/src/include/portability.h"
11 #include "native_client/src/trusted/validator_ragel/validator.h"
12
13 #ifndef O_BINARY
14 # define O_BINARY 0
15 #endif
16
17 static void *g_contents;
18 static size_t g_contents_size;
19 static uint8_t *g_code_start;
20 static Elf32_Addr g_code_addr;
21 static int g_errors;
22 static int g_changes;
23
24 static void ReportError(const void *insn, const char *message) {
25 Elf32_Addr insn_addr = (Elf32_Addr) ((uint8_t *) insn - g_code_start) +
26 g_code_addr;
27
28 fprintf(stderr, "%#x: %s\n", (unsigned int) insn_addr, message);
29 ++g_errors;
30 }
31
32 static void EditArmCode(void *code, size_t code_length) {
33 Elf32_Word *const words = code;
34 Elf32_Word *const end = (void *) ((uint8_t *) code + code_length);
35 Elf32_Word *insn;
36
37 for (insn = words; insn < end; ++insn) {
38 if (*insn == NACL_INSTR_ARM_LITERAL_POOL_HEAD) {
39 if ((insn - words) % 4 != 0) {
40 ReportError(insn, "Roadblock not at start of bundle");
41 } else {
42 /*
43 * Ignore the rest of this bundle.
44 */
45 insn += 3;
46 }
47 } else if ((*insn & 0x0FFF0FFF) == 0x05990000) {
48 /*
49 * This is 'ldr REG, [r9, #0]'.
50 * Turn it into 'ldr REG, [r9, #4]'.
51 */
52 *insn |= 4;
53 ++g_changes;
54 }
55 }
56 }
57
58 static Bool ConsiderOneInsn(const uint8_t *insn_begin, const uint8_t *insn_end,
59 uint32_t validation_info, void *data) {
60 UNREFERENCED_PARAMETER(data);
61 if (insn_begin[0] == 0x65) { /* GS prefix */
62 if (insn_end - insn_begin < 6) {
63 ReportError(insn_begin, "Unexpected GS prefix");
64 } else if (insn_end[-1] != 0 || insn_end[-2] != 0 ||
65 insn_end[-3] != 0 || insn_end[-4] != 0) {
66 ReportError(insn_begin, "Unexpected %gs address");
67 } else {
68 /*
69 * This is 'something %gs:0'.
70 * Turn it into 'something %gs:4'.
71 */
72 ((uint8_t *) insn_end)[-4] = 4;
73 ++g_changes;
74 }
75 }
76
77 return (validation_info & (VALIDATION_ERRORS_MASK | BAD_JUMP_TARGET)) == 0;
78 }
79
80 static void EditX86_32Code(void *code, size_t code_length) {
81 const NaClCPUFeaturesX86* cpu_features = &kFullCPUIDFeatures;
82 if (!ValidateChunkIA32(code, code_length,
83 CALL_USER_CALLBACK_ON_EACH_INSTRUCTION,
84 cpu_features, &ConsiderOneInsn, NULL))
85 ReportError(code, "Validation failed");
86 }
87
88 static void ReadInput(const char *filename) {
89 struct stat st;
90 FILE *fp = fopen(filename, "rb");
91 if (fp == NULL) {
92 fprintf(stderr, "open: %s: %s\n",
Roland McGrath 2014/01/24 18:50:49 Say fopen in the message since that's what you cal
93 filename, strerror(errno));
94 exit(1);
95 }
96
97 if (fstat(fileno(fp), &st) < 0) {
98 fprintf(stderr, "fstat: %s: %s\n",
99 filename, strerror(errno));
100 exit(1);
101 }
102
103 g_contents_size = st.st_size;
104 g_contents = malloc(g_contents_size);
105 if (g_contents == NULL) {
106 fprintf(stderr, "Cannot allocate %u bytes: %s\n",
107 (unsigned int) st.st_size, strerror(errno));
108 exit(1);
109 }
110
111 {
112 size_t read_bytes = fread(g_contents, 1, g_contents_size, fp);
113 if (read_bytes != g_contents_size) {
114 int error_num = ferror(fp);
Roland McGrath 2014/01/24 18:50:49 ferror and feof return a Boolean value, not an err
115 int eof_error = feof(fp);
116 if (error_num) {
117 fprintf(stderr, "read: %s: %s\n",
Roland McGrath 2014/01/24 18:50:49 Say fread in the messages since that's what you ca
118 filename, strerror(error_num));
119 } else if (eof_error) {
120 fprintf(stderr, "read: %s: premature EOF: %s\n",
121 filename, strerror(eof_error));
122 } else {
123 fprintf(stderr, "read: %s: unknown error\n",
124 filename);
125 }
126 exit(1);
127 }
128 }
129
130 fclose(fp);
131 }
132
133 static void WriteOutput(const char *filename) {
134 FILE *fp = fopen(filename, "wb+");
135 if (fp == NULL) {
136 fprintf(stderr, "open: %s: %s\n", filename, strerror(errno));
137 exit(1);
138 }
139
140 {
141 size_t nwrote = fwrite(g_contents, 1, g_contents_size, fp);
142 if (nwrote != g_contents_size) {
143 fprintf(stderr, "write: %s: %s\n", filename, strerror(errno));
144 exit(1);
145 }
146 }
147
148 fclose(fp);
149 }
150
151 static Bool Process32BitFile(const char* infile)
Roland McGrath 2014/01/24 18:50:49 brace on end of decl line
Roland McGrath 2014/01/24 18:50:49 'const char *infile'. This is C, not C++.
152 {
153 const Elf32_Ehdr *ehdr;
154 const Elf32_Phdr *phdr;
155 size_t code_length;
156 int i;
157
158 ehdr = g_contents;
159 if (ehdr->e_phoff > g_contents_size) {
160 fprintf(stderr, "%s: bogus e_phoff\n",
161 infile);
162 return FALSE;
163 }
164 if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
165 fprintf(stderr, "%s: not an ELFCLASS32 file\n",
166 infile);
167 return FALSE;
168 }
169 if (ehdr->e_phentsize != sizeof(Elf32_Phdr)) {
170 fprintf(stderr, "%s: wrong e_phentsize: %u\n",
171 infile, ehdr->e_phentsize);
172 return FALSE;
173 }
174 if (g_contents_size - ehdr->e_phoff < ehdr->e_phnum * sizeof(Elf32_Phdr)) {
175 fprintf(stderr, "%s: bogus elf32 e_phnum\n",
176 infile);
177 return FALSE;
178 }
179
180 if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
181 fprintf(stderr, "%s: not an ELFDATA2LSB file\n",
182 infile);
183 return FALSE;
184 }
185
186 phdr = (const void *) ((uint8_t *) g_contents + ehdr->e_phoff);
187 for (i = 0; i < ehdr->e_phnum; ++i) {
188 if (phdr[i].p_type == PT_LOAD && (phdr[i].p_flags & PF_X) != 0)
189 break;
190 }
191 if (i == ehdr->e_phnum) {
192 fprintf(stderr, "%s: Could not find executable load segment!\n",
193 infile);
194 return FALSE;
195 }
196
197 if (phdr[i].p_offset > g_contents_size ||
Roland McGrath 2014/01/24 18:50:49 Don't repeat all this logic in the 32/64 variants.
198 g_contents_size - phdr[i].p_offset < phdr[i].p_filesz) {
199 fprintf(stderr, "%s: Program header %d has invalid offset or size!\n",
200 infile, i);
201 return FALSE;
202 }
203
204 g_code_addr = phdr[i].p_vaddr;
205 g_code_start = (uint8_t *) g_contents + phdr[i].p_offset;
206 code_length = phdr[i].p_filesz;
207
208 switch (ehdr->e_machine) {
209 case EM_ARM:
210 EditArmCode(g_code_start, code_length);
211 break;
212 case EM_386:
213 EditX86_32Code(g_code_start, code_length);
214 break;
215 default:
216 fprintf(stderr, "%s: Unsupported e_machine %d\n",
217 infile, ehdr->e_machine);
218 return FALSE;
219 }
220
221 if (g_changes == 0) {
222 fprintf(stderr, "%s: Found no changes to make!\n",
223 infile);
224 return FALSE;
225 } else {
226 printf("%s: %d instructions changed\n",
227 infile, g_changes);
228 }
229
230 return TRUE;
231 }
232
233 static Bool Process64BitFile(const char* infile)
Roland McGrath 2014/01/24 18:50:49 brace at end of decl line
234 {
235 const Elf64_Ehdr *ehdr;
236
237 ehdr = g_contents;
238 if (ehdr->e_phoff > g_contents_size) {
239 fprintf(stderr, "%s: bogus e_phoff\n",
240 infile);
241 return FALSE;
242 }
243 if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) {
244 fprintf(stderr, "%s: not an ELFCLASS64 file\n",
245 infile);
246 return FALSE;
247 }
248 if (ehdr->e_phentsize != sizeof(Elf64_Phdr)) {
249 fprintf(stderr, "%s: wrong e_phentsize: %u\n",
250 infile, ehdr->e_phentsize);
251 return FALSE;
252 }
253 if (g_contents_size - ehdr->e_phoff < ehdr->e_phnum * sizeof(Elf64_Phdr)) {
254 fprintf(stderr, "%s: bogus elf64 e_phnum\n",
255 infile);
256 return FALSE;
257 }
258
259 if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
260 fprintf(stderr, "%s: not an ELFDATA2LSB file\n",
261 infile);
262 return FALSE;
263 }
264
265 switch (ehdr->e_machine) {
266 case EM_X86_64:
267 printf("%s: x86-64 ELF detected, no instructions changed\n",
268 infile);
269 return TRUE;
270 default:
271 fprintf(stderr, "%s: Unsupported e_machine %d\n",
272 infile, ehdr->e_machine);
273 return FALSE;
274 }
275
276 if (g_changes == 0) {
277 fprintf(stderr, "%s: Found no changes to make!\n",
278 infile);
279 return FALSE;
280 } else {
281 printf("%s: %d instructions changed\n",
282 infile, g_changes);
283 }
284
285 return TRUE;
286 }
287
288 int main(int argc, char **argv) {
289 const char *infile;
290 const char *outfile;
291
292 if (argc != 3) {
293 fprintf(stderr, "Usage: %s INFILE OUTFILE\n", argv[0]);
294 return 1;
295 }
296
297 infile = argv[1];
298 outfile = argv[2];
299
300 ReadInput(infile);
301
302 if (g_contents_size < SELFMAG) {
303 fprintf(stderr, "%s: too short to be an ELF file\n",
304 infile);
305 return 1;
306 }
307 if (memcmp(g_contents, ELFMAG, SELFMAG) != 0) {
308 fprintf(stderr, "%s: not an ELF file\n",
309 infile);
310 return 1;
311 }
312
313 /*
314 * We will examine the header to figure out whether or not we are dealing
315 * with a 32 bit or 64 bit executable file.
316 */
317 if (g_contents_size >= sizeof(Elf32_Ehdr) &&
318 ((Elf32_Ehdr*)g_contents)->e_ident[EI_CLASS] == ELFCLASS32) {
Roland McGrath 2014/01/24 18:50:49 space before * and after ): '(Elf32_Ehdr *) g_cont
319 if (!Process32BitFile(infile)) {
320 fprintf(stderr, "%s: Could not process 32 bit ELF file\n",
321 infile);
322 return 1;
323 }
324 } else if (g_contents_size >= sizeof(Elf64_Ehdr) &&
325 ((Elf64_Ehdr*)g_contents)->e_ident[EI_CLASS] == ELFCLASS64) {
326 if (!Process64BitFile(infile)) {
327 fprintf(stderr, "%s: Could not process 64 bit ELF file\n",
328 infile);
329 return 1;
330 }
331 } else {
332 fprintf(stderr, "%s: Invalid ELF file!\n",
333 infile);
334 return 1;
335 }
336
337 if (g_errors != 0)
338 return 1;
339
340 WriteOutput(outfile);
341 return 0;
342 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698