Mercurial > hg > chrpath
comparison chrpath.c @ 0:b8f7423e385c
import 0.13
| author | Peter Meerwald <pmeerw@pmeerw.net> |
|---|---|
| date | Fri, 20 Jul 2012 01:51:24 +0200 |
| parents | |
| children | bbbfb3f97919 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:b8f7423e385c |
|---|---|
| 1 /* | |
| 2 <URL:http://gcc.gnu.org/ml/gcc/1999-04n/msg01105.html> | |
| 3 | |
| 4 Re: changing embedded RPATH in existing executables. | |
| 5 | |
| 6 To: geoffk@ozemail.com.au | |
| 7 Subject: Re: changing embedded RPATH in existing executables. | |
| 8 From: <peeter_joot@VNET.IBM.COM> (peeter joot) | |
| 9 Date: Fri, 30 Apr 1999 16:14:44 -0400 (EDT) | |
| 10 Cc: peeterj@ca.ibm.com, egcs@cygnus.com, libc-hacker@cygnus.com, linux-gcc@vger.rutgers.edu | |
| 11 Reply-To: <peeter_joot@VNET.IBM.COM> | |
| 12 | |
| 13 > _Changing_ is a little tricky, but the attached program strips rpaths | |
| 14 > from executables (I find it essential for debugging the binutils). | |
| 15 > It's endian-dependent, if you want this for x86 you can just change | |
| 16 > the occurrences of 'MSB' to 'LSB' and compile (I should really fix | |
| 17 > that). | |
| 18 | |
| 19 Hi Geoff, | |
| 20 | |
| 21 With your program as a guide (and some peeks into libbfd, elf.h, a bit | |
| 22 of the glibc dynamic loader code, objdump, and a hex-editor) I was able to | |
| 23 figure out enough to find and change the rpath string. That was fun! | |
| 24 | |
| 25 This program assumes (unlike your original program) that there is only | |
| 26 one DT_RPATH tag in the dynamic section as even with multiple '-Wl,-rpath,' | |
| 27 commands in the link this seems to occur (they all get concatonated into | |
| 28 a : separated path). | |
| 29 | |
| 30 Thanks for your help. If you want to use this on non-x86 you have to change | |
| 31 the occurances of LSB back to MSB:) | |
| 32 | |
| 33 Peeter | |
| 34 -- | |
| 35 */ | |
| 36 | |
| 37 #ifdef HAVE_CONFIG_H | |
| 38 # include "config.h" | |
| 39 #endif | |
| 40 | |
| 41 #include <stdio.h> | |
| 42 #include <unistd.h> | |
| 43 #include <fcntl.h> | |
| 44 #include <elf.h> | |
| 45 #if defined(HAVE_LINK_H) | |
| 46 # include <link.h> | |
| 47 #endif /* HAVE_LINK_H */ | |
| 48 #include <stdlib.h> | |
| 49 #include <string.h> | |
| 50 #include <sys/stat.h> | |
| 51 #include "protos.h" | |
| 52 | |
| 53 /** | |
| 54 * Reads an ELF file, and reads or alters the RPATH setting. | |
| 55 * | |
| 56 * TODO: | |
| 57 * modify to add RPATH setting if none exists. | |
| 58 */ | |
| 59 | |
| 60 | |
| 61 int | |
| 62 chrpath(const char *filename, const char *newpath, int convert) | |
| 63 { | |
| 64 int fd; | |
| 65 Elf_Ehdr ehdr; | |
| 66 int i; | |
| 67 Elf_Phdr phdr; | |
| 68 Elf_Shdr shdr; | |
| 69 Elf_Dyn *dyns; | |
| 70 int rpathoff; | |
| 71 char * strtab; | |
| 72 char * rpath; | |
| 73 unsigned int rpathlen; | |
| 74 int oflags; | |
| 75 int rpath_dyns_index; | |
| 76 | |
| 77 if (NULL == newpath && 0 == convert) | |
| 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 { | |
| 91 perror("found no dynamic section"); | |
| 92 return 1; | |
| 93 } | |
| 94 | |
| 95 dyns = malloc(phdr.p_filesz); | |
| 96 if (dyns == NULL) | |
| 97 { | |
| 98 perror ("allocating memory for dynamic section"); | |
| 99 return 1; | |
| 100 } | |
| 101 memset(dyns, 0, phdr.p_filesz); | |
| 102 if (lseek(fd, phdr.p_offset, SEEK_SET) == -1 | |
| 103 || read(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz) | |
| 104 { | |
| 105 perror ("reading dynamic section"); | |
| 106 free(dyns); | |
| 107 return 1; | |
| 108 } | |
| 109 | |
| 110 rpathoff = -1; | |
| 111 for ( rpath_dyns_index = 0; dyns[rpath_dyns_index].d_tag != DT_NULL; | |
| 112 ++rpath_dyns_index ) | |
| 113 { | |
| 114 if ( elf_dynpath_tag(dyns[rpath_dyns_index].d_tag) ) | |
| 115 { | |
| 116 rpathoff = dyns[rpath_dyns_index].d_un.d_ptr; | |
| 117 break; | |
| 118 } | |
| 119 } | |
| 120 if (rpathoff == -1) | |
| 121 { | |
| 122 printf("%s: no rpath or runpath tag found.\n", filename); | |
| 123 free(dyns); | |
| 124 return 2; | |
| 125 } | |
| 126 | |
| 127 if (lseek(fd, ehdr.e_shoff, SEEK_SET) == -1) | |
| 128 { | |
| 129 perror ("positioning for sections"); | |
| 130 free(dyns); | |
| 131 return 1; | |
| 132 } | |
| 133 | |
| 134 for (i = 0; i < ehdr.e_shnum; i++) | |
| 135 { | |
| 136 if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) | |
| 137 { | |
| 138 perror ("reading section header"); | |
| 139 free(dyns); | |
| 140 return 1; | |
| 141 } | |
| 142 if (shdr.sh_type == SHT_STRTAB) | |
| 143 break; | |
| 144 } | |
| 145 if (i == ehdr.e_shnum) | |
| 146 { | |
| 147 fprintf (stderr, "No string table found.\n"); | |
| 148 free(dyns); | |
| 149 return 2; | |
| 150 } | |
| 151 strtab = (char *)malloc(shdr.sh_size); | |
| 152 if (strtab == NULL) | |
| 153 { | |
| 154 perror ("allocating memory for string table"); | |
| 155 free(dyns); | |
| 156 return 1; | |
| 157 } | |
| 158 memset(strtab, 0, shdr.sh_size); | |
| 159 | |
| 160 if (lseek(fd, shdr.sh_offset, SEEK_SET) == -1) | |
| 161 { | |
| 162 perror ("positioning for string table"); | |
| 163 free(strtab); | |
| 164 free(dyns); | |
| 165 return 1; | |
| 166 } | |
| 167 if (read(fd, strtab, shdr.sh_size) != (int)shdr.sh_size) | |
| 168 { | |
| 169 perror ("reading string table"); | |
| 170 free(strtab); | |
| 171 free(dyns); | |
| 172 return 1; | |
| 173 } | |
| 174 | |
| 175 if ((int)shdr.sh_size < rpathoff) | |
| 176 { | |
| 177 fprintf(stderr, "%s string offset not contained in string table", | |
| 178 elf_tagname(dyns[rpath_dyns_index].d_tag)); | |
| 179 free(strtab); | |
| 180 free(dyns); | |
| 181 return 5; | |
| 182 } | |
| 183 rpath = strtab+rpathoff; | |
| 184 | |
| 185 #if defined(DT_RUNPATH) | |
| 186 if (convert && dyns[rpath_dyns_index].d_tag == DT_RPATH) | |
| 187 { | |
| 188 dyns[rpath_dyns_index].d_tag = DT_RUNPATH; | |
| 189 if (lseek(fd, phdr.p_offset, SEEK_SET) == -1 | |
| 190 || write(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz) | |
| 191 { | |
| 192 perror ("converting RPATH to RUNPATH"); | |
| 193 return 1; | |
| 194 } | |
| 195 printf("%s: RPATH converted to RUNPATH\n", filename); | |
| 196 } | |
| 197 #endif /* DT_RUNPATH */ | |
| 198 | |
| 199 printf("%s: %s=%s\n", filename, elf_tagname(dyns[rpath_dyns_index].d_tag), | |
| 200 rpath); | |
| 201 | |
| 202 if (NULL == newpath) | |
| 203 { | |
| 204 free(dyns); | |
| 205 free(strtab); | |
| 206 return 0; | |
| 207 } | |
| 208 | |
| 209 rpathlen = strlen(rpath); | |
| 210 | |
| 211 /* | |
| 212 * Calculate the maximum rpath length (will be equal to rpathlen unless | |
| 213 * we have previously truncated it). | |
| 214 */ | |
| 215 for ( i = rpathoff + rpathlen ; (i < (int)shdr.sh_size | |
| 216 && strtab[i] == '\0') ; i++ ) | |
| 217 ; | |
| 218 i--; | |
| 219 | |
| 220 if (i > (int)(rpathoff + rpathlen)) | |
| 221 rpathlen = i - rpathoff; | |
| 222 | |
| 223 if (strlen(newpath) > rpathlen) | |
| 224 { | |
| 225 fprintf(stderr, "new rpath '%s' too large; maximum length %i\n", | |
| 226 newpath, rpathlen); | |
| 227 free(dyns); | |
| 228 free(strtab); | |
| 229 return 7; | |
| 230 } | |
| 231 | |
| 232 memset(rpath, 0, rpathlen); | |
| 233 strcpy(rpath, newpath); | |
| 234 | |
| 235 if (lseek(fd, shdr.sh_offset+rpathoff, SEEK_SET) == -1) | |
| 236 { | |
| 237 perror ("positioning for RPATH"); | |
| 238 free(dyns); | |
| 239 free(strtab); | |
| 240 return 1; | |
| 241 } | |
| 242 if (write(fd, rpath, rpathlen) != (int)rpathlen) | |
| 243 { | |
| 244 perror ("writing RPATH"); | |
| 245 free(dyns); | |
| 246 free(strtab); | |
| 247 return 1; | |
| 248 } | |
| 249 printf("%s: new %s: %s\n", filename, | |
| 250 elf_tagname(dyns[rpath_dyns_index].d_tag), rpath); | |
| 251 | |
| 252 elf_close(fd); | |
| 253 | |
| 254 free(dyns); | |
| 255 dyns = NULL; | |
| 256 | |
| 257 free(strtab); | |
| 258 | |
| 259 return 0; | |
| 260 } |
