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