Created
May 21, 2011 17:40
-
-
Save r2k0/984710 to your computer and use it in GitHub Desktop.
fix RPATH
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <elf.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
int | |
main(int argc, char **argv) | |
{ | |
int fd; | |
Elf32_Ehdr ehdr; | |
int i; | |
Elf32_Phdr phdr; | |
Elf32_Shdr shdr; | |
Elf32_Dyn *dyns; | |
int rpathoff; | |
char * strtab; | |
char * rpath; | |
int rpathlen; | |
int oflags; | |
if (argc != 2 && argc != 3) | |
{ | |
printf ("Usage: %s objectfile [new-rpath]\n", argv[0]); | |
return 1; | |
} | |
if (argc == 2) | |
oflags = O_RDONLY; | |
else | |
oflags = O_RDWR; | |
fd = open(argv[1], oflags); | |
if (fd == -1) | |
{ | |
perror ("open"); | |
return 1; | |
} | |
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) | |
{ | |
perror ("reading header"); | |
return 1; | |
} | |
if (*(unsigned *)ehdr.e_ident != *(const unsigned *)ELFMAG || | |
ehdr.e_ident[EI_CLASS] != ELFCLASS32 || | |
ehdr.e_ident[EI_DATA] != ELFDATA2LSB || | |
ehdr.e_ident[EI_VERSION] != EV_CURRENT) | |
{ | |
fprintf(stderr, "`%s' probably isn't a 32-bit LSB-first ELF file.\n", | |
argv[1]); | |
return 1; | |
} | |
if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) | |
{ | |
fprintf(stderr, "section size was read as %d, not %d!\n", | |
ehdr.e_phentsize, sizeof(Elf32_Phdr)); | |
return 1; | |
} | |
if (lseek(fd, ehdr.e_phoff, SEEK_SET) == -1) | |
{ | |
perror ("positioning for sections"); | |
return 1; | |
} | |
for (i = 0; i < ehdr.e_phnum; i++) | |
{ | |
if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) | |
{ | |
perror ("reading section header"); | |
return 1; | |
} | |
if (phdr.p_type == PT_DYNAMIC) | |
break; | |
} | |
if (i == ehdr.e_phnum) | |
{ | |
fprintf (stderr, "No dynamic section found.\n"); | |
return 2; | |
} | |
dyns = malloc(phdr.p_memsz); | |
if (dyns == NULL) | |
{ | |
perror ("allocating memory for dynamic section"); | |
return 1; | |
} | |
memset(dyns, 0, phdr.p_memsz); | |
if (lseek(fd, phdr.p_offset, SEEK_SET) == -1 | |
|| read(fd, dyns, phdr.p_filesz) != phdr.p_filesz) | |
{ | |
perror ("reading dynamic section"); | |
return 1; | |
} | |
rpathoff = -1; | |
for (i = 0; dyns[i].d_tag != DT_NULL; i++) | |
{ | |
if (dyns[i].d_tag == DT_RPATH) | |
{ | |
rpathoff = dyns[i].d_un.d_ptr; | |
break; | |
} | |
} | |
if (rpathoff == -1) | |
{ | |
fprintf (stderr, "No rpath tag found.\n"); | |
return 2; | |
} | |
if (lseek(fd, ehdr.e_shoff, SEEK_SET) == -1) | |
{ | |
perror ("positioning for sections"); | |
return 1; | |
} | |
for (i = 0; i < ehdr.e_shnum; i++) | |
{ | |
if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) | |
{ | |
perror ("reading section header"); | |
return 1; | |
} | |
if (shdr.sh_type == SHT_STRTAB) | |
break; | |
} | |
if (i == ehdr.e_shnum) | |
{ | |
fprintf (stderr, "No string table found.\n"); | |
return 2; | |
} | |
strtab = (char *)malloc(shdr.sh_size); | |
if (strtab == NULL) | |
{ | |
perror ("allocating memory for string table"); | |
return 1; | |
} | |
memset(strtab, 0, shdr.sh_size); | |
if (lseek(fd, shdr.sh_offset, SEEK_SET) == -1) | |
{ | |
perror ("positioning for string table"); | |
return 1; | |
} | |
if (read(fd, strtab, shdr.sh_size) != shdr.sh_size) | |
{ | |
perror ("reading string table"); | |
return 1; | |
} | |
if (shdr.sh_size < rpathoff) | |
{ | |
fprintf(stderr, "RPATH string offset not contained in string table"); | |
return 5; | |
} | |
rpath = strtab+rpathoff; | |
printf("%s:existing RPATH: %s\n", argv[1], rpath); | |
if (argc == 2) | |
return 0; | |
rpathlen = strlen(rpath); | |
for ( i = rpathoff + rpathlen ; i < shdr.sh_size && strtab[i] == '\0' ; i++ ); | |
i--; | |
if (i> rpathoff + rpathlen) | |
rpathlen = i - rpathoff; | |
if (strlen(argv[2]) > rpathlen) | |
{ | |
fprintf(stderr, "new rpath '%s' too large; maximum length %i\n", | |
argv[2], rpathlen); | |
return 7; | |
} | |
memset(rpath, 0, rpathlen); | |
strcpy(rpath, argv[2]); | |
if (lseek(fd, shdr.sh_offset+rpathoff, SEEK_SET) == -1) | |
{ | |
perror ("positioning for RPATH"); | |
return 1; | |
} | |
if (write(fd, rpath, rpathlen) != rpathlen) | |
{ | |
perror ("writing RPATH"); | |
return 1; | |
} | |
printf("%s:new RPATH: %s\n", argv[1], rpath); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment