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 } |
