Mercurial > hg > chrpath
comparison chrpath.c @ 1:bbbfb3f97919
implement 32 and 64 bit support
author | Peter Meerwald <p.meerwald@bct-electronic.com> |
---|---|
date | Fri, 20 Jul 2012 11:26:24 +0200 |
parents | b8f7423e385c |
children |
comparison
equal
deleted
inserted
replaced
0:b8f7423e385c | 1:bbbfb3f97919 |
---|---|
56 * TODO: | 56 * TODO: |
57 * modify to add RPATH setting if none exists. | 57 * modify to add RPATH setting if none exists. |
58 */ | 58 */ |
59 | 59 |
60 | 60 |
61 int | 61 static int |
62 chrpath(const char *filename, const char *newpath, int convert) | 62 chrpath32(int fd, const char *filename, const char *newpath, Elf32_Ehdr *ehdr, int convert) { |
63 { | 63 Elf32_Phdr phdr; |
64 int fd; | 64 Elf32_Shdr shdr; |
65 Elf_Ehdr ehdr; | 65 Elf32_Dyn *dyns; |
66 int i; | 66 int i; |
67 Elf_Phdr phdr; | |
68 Elf_Shdr shdr; | |
69 Elf_Dyn *dyns; | |
70 int rpathoff; | 67 int rpathoff; |
71 char * strtab; | 68 char * strtab; |
72 char * rpath; | 69 char * rpath; |
73 unsigned int rpathlen; | 70 unsigned int rpathlen; |
74 int oflags; | |
75 int rpath_dyns_index; | 71 int rpath_dyns_index; |
76 | 72 |
77 if (NULL == newpath && 0 == convert) | 73 if (0 != elf32_find_dynamic_section(fd, ehdr, &phdr)) |
78 oflags = O_RDONLY; | |
79 else | |
80 oflags = O_RDWR; | |
81 | |
82 fd = elf_open(filename, oflags, &ehdr); | |
83 if (fd == -1) | |
84 { | |
85 perror ("elf_open"); | |
86 return 1; | |
87 } | |
88 | |
89 if (0 != elf_find_dynamic_section(fd, &ehdr, &phdr)) | |
90 { | 74 { |
91 perror("found no dynamic section"); | 75 perror("found no dynamic section"); |
92 return 1; | 76 return 1; |
93 } | 77 } |
94 | 78 |
122 printf("%s: no rpath or runpath tag found.\n", filename); | 106 printf("%s: no rpath or runpath tag found.\n", filename); |
123 free(dyns); | 107 free(dyns); |
124 return 2; | 108 return 2; |
125 } | 109 } |
126 | 110 |
127 if (lseek(fd, ehdr.e_shoff, SEEK_SET) == -1) | 111 if (lseek(fd, ehdr->e_shoff, SEEK_SET) == -1) |
128 { | 112 { |
129 perror ("positioning for sections"); | 113 perror ("positioning for sections"); |
130 free(dyns); | 114 free(dyns); |
131 return 1; | 115 return 1; |
132 } | 116 } |
133 | 117 |
134 for (i = 0; i < ehdr.e_shnum; i++) | 118 for (i = 0; i < ehdr->e_shnum; i++) |
135 { | 119 { |
136 if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) | 120 if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) |
137 { | 121 { |
138 perror ("reading section header"); | 122 perror ("reading section header"); |
139 free(dyns); | 123 free(dyns); |
140 return 1; | 124 return 1; |
141 } | 125 } |
142 if (shdr.sh_type == SHT_STRTAB) | 126 if (shdr.sh_type == SHT_STRTAB) |
143 break; | 127 break; |
144 } | 128 } |
145 if (i == ehdr.e_shnum) | 129 if (i == ehdr->e_shnum) |
146 { | 130 { |
147 fprintf (stderr, "No string table found.\n"); | 131 fprintf (stderr, "No string table found.\n"); |
148 free(dyns); | 132 free(dyns); |
149 return 2; | 133 return 2; |
150 } | 134 } |
256 | 240 |
257 free(strtab); | 241 free(strtab); |
258 | 242 |
259 return 0; | 243 return 0; |
260 } | 244 } |
245 | |
246 static int | |
247 chrpath64(int fd, const char *filename, const char *newpath, Elf64_Ehdr *ehdr, int convert) { | |
248 Elf64_Phdr phdr; | |
249 Elf64_Shdr shdr; | |
250 Elf64_Dyn *dyns; | |
251 int i; | |
252 int rpathoff; | |
253 char * strtab; | |
254 char * rpath; | |
255 unsigned int rpathlen; | |
256 int rpath_dyns_index; | |
257 | |
258 if (0 != elf64_find_dynamic_section(fd, ehdr, &phdr)) | |
259 { | |
260 perror("found no dynamic section"); | |
261 return 1; | |
262 } | |
263 | |
264 dyns = malloc(phdr.p_filesz); | |
265 if (dyns == NULL) | |
266 { | |
267 perror ("allocating memory for dynamic section"); | |
268 return 1; | |
269 } | |
270 memset(dyns, 0, phdr.p_filesz); | |
271 if (lseek(fd, phdr.p_offset, SEEK_SET) == -1 | |
272 || read(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz) | |
273 { | |
274 perror ("reading dynamic section"); | |
275 free(dyns); | |
276 return 1; | |
277 } | |
278 | |
279 rpathoff = -1; | |
280 for ( rpath_dyns_index = 0; dyns[rpath_dyns_index].d_tag != DT_NULL; | |
281 ++rpath_dyns_index ) | |
282 { | |
283 if ( elf_dynpath_tag(dyns[rpath_dyns_index].d_tag) ) | |
284 { | |
285 rpathoff = dyns[rpath_dyns_index].d_un.d_ptr; | |
286 break; | |
287 } | |
288 } | |
289 if (rpathoff == -1) | |
290 { | |
291 printf("%s: no rpath or runpath tag found.\n", filename); | |
292 free(dyns); | |
293 return 2; | |
294 } | |
295 | |
296 if (lseek(fd, ehdr->e_shoff, SEEK_SET) == -1) | |
297 { | |
298 perror ("positioning for sections"); | |
299 free(dyns); | |
300 return 1; | |
301 } | |
302 | |
303 for (i = 0; i < ehdr->e_shnum; i++) | |
304 { | |
305 if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) | |
306 { | |
307 perror ("reading section header"); | |
308 free(dyns); | |
309 return 1; | |
310 } | |
311 if (shdr.sh_type == SHT_STRTAB) | |
312 break; | |
313 } | |
314 if (i == ehdr->e_shnum) | |
315 { | |
316 fprintf (stderr, "No string table found.\n"); | |
317 free(dyns); | |
318 return 2; | |
319 } | |
320 strtab = (char *)malloc(shdr.sh_size); | |
321 if (strtab == NULL) | |
322 { | |
323 perror ("allocating memory for string table"); | |
324 free(dyns); | |
325 return 1; | |
326 } | |
327 memset(strtab, 0, shdr.sh_size); | |
328 | |
329 if (lseek(fd, shdr.sh_offset, SEEK_SET) == -1) | |
330 { | |
331 perror ("positioning for string table"); | |
332 free(strtab); | |
333 free(dyns); | |
334 return 1; | |
335 } | |
336 if (read(fd, strtab, shdr.sh_size) != (int)shdr.sh_size) | |
337 { | |
338 perror ("reading string table"); | |
339 free(strtab); | |
340 free(dyns); | |
341 return 1; | |
342 } | |
343 | |
344 if ((int)shdr.sh_size < rpathoff) | |
345 { | |
346 fprintf(stderr, "%s string offset not contained in string table", | |
347 elf_tagname(dyns[rpath_dyns_index].d_tag)); | |
348 free(strtab); | |
349 free(dyns); | |
350 return 5; | |
351 } | |
352 rpath = strtab+rpathoff; | |
353 | |
354 #if defined(DT_RUNPATH) | |
355 if (convert && dyns[rpath_dyns_index].d_tag == DT_RPATH) | |
356 { | |
357 dyns[rpath_dyns_index].d_tag = DT_RUNPATH; | |
358 if (lseek(fd, phdr.p_offset, SEEK_SET) == -1 | |
359 || write(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz) | |
360 { | |
361 perror ("converting RPATH to RUNPATH"); | |
362 return 1; | |
363 } | |
364 printf("%s: RPATH converted to RUNPATH\n", filename); | |
365 } | |
366 #endif /* DT_RUNPATH */ | |
367 | |
368 printf("%s: %s=%s\n", filename, elf_tagname(dyns[rpath_dyns_index].d_tag), | |
369 rpath); | |
370 | |
371 if (NULL == newpath) | |
372 { | |
373 free(dyns); | |
374 free(strtab); | |
375 return 0; | |
376 } | |
377 | |
378 rpathlen = strlen(rpath); | |
379 | |
380 /* | |
381 * Calculate the maximum rpath length (will be equal to rpathlen unless | |
382 * we have previously truncated it). | |
383 */ | |
384 for ( i = rpathoff + rpathlen ; (i < (int)shdr.sh_size | |
385 && strtab[i] == '\0') ; i++ ) | |
386 ; | |
387 i--; | |
388 | |
389 if (i > (int)(rpathoff + rpathlen)) | |
390 rpathlen = i - rpathoff; | |
391 | |
392 if (strlen(newpath) > rpathlen) | |
393 { | |
394 fprintf(stderr, "new rpath '%s' too large; maximum length %i\n", | |
395 newpath, rpathlen); | |
396 free(dyns); | |
397 free(strtab); | |
398 return 7; | |
399 } | |
400 | |
401 memset(rpath, 0, rpathlen); | |
402 strcpy(rpath, newpath); | |
403 | |
404 if (lseek(fd, shdr.sh_offset+rpathoff, SEEK_SET) == -1) | |
405 { | |
406 perror ("positioning for RPATH"); | |
407 free(dyns); | |
408 free(strtab); | |
409 return 1; | |
410 } | |
411 if (write(fd, rpath, rpathlen) != (int)rpathlen) | |
412 { | |
413 perror ("writing RPATH"); | |
414 free(dyns); | |
415 free(strtab); | |
416 return 1; | |
417 } | |
418 printf("%s: new %s: %s\n", filename, | |
419 elf_tagname(dyns[rpath_dyns_index].d_tag), rpath); | |
420 | |
421 elf_close(fd); | |
422 | |
423 free(dyns); | |
424 dyns = NULL; | |
425 | |
426 free(strtab); | |
427 | |
428 return 0; | |
429 } | |
430 | |
431 int | |
432 chrpath(const char *filename, const char *newpath, int convert) | |
433 { | |
434 int fd; | |
435 Elf32_Ehdr ehdr32; | |
436 Elf64_Ehdr ehdr64; | |
437 int oflags; | |
438 | |
439 if (NULL == newpath && 0 == convert) | |
440 oflags = O_RDONLY; | |
441 else | |
442 oflags = O_RDWR; | |
443 | |
444 fd = elf32_open(filename, oflags, &ehdr32); | |
445 if (fd >= 0) | |
446 return chrpath32(fd, filename, newpath, &ehdr32, convert); | |
447 | |
448 fd = elf64_open(filename, oflags, &ehdr64); | |
449 if (fd >= 0) | |
450 return chrpath64(fd, filename, newpath, &ehdr64, convert); | |
451 | |
452 perror ("elf_open"); | |
453 return 1; | |
454 } |