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 }

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.