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 }

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