Mercurial > hg > chrpath
annotate elf.c @ 2:7bf4a164d5bb default tip
fix bug: long_options have to be zero terminated
author | Peter Meerwald <p.meerwald@bct-electronic.com> |
---|---|
date | Fri, 20 Jul 2012 11:28:30 +0200 |
parents | bbbfb3f97919 |
children |
rev | line source |
---|---|
0 | 1 |
2 #ifdef HAVE_CONFIG_H | |
3 # include "config.h" | |
4 #endif | |
5 | |
6 #include <elf.h> | |
7 #if defined(HAVE_SYS_LINK_H) | |
8 # include <sys/link.h> /* Find DT_RPATH on Solaris 2.6 */ | |
9 #endif /* HAVE_SYS_LINK_H */ | |
10 #include <stdio.h> | |
11 #include <string.h> | |
12 #include <unistd.h> | |
13 #include <sys/types.h> | |
14 #include <sys/stat.h> | |
15 #include <errno.h> | |
16 #include <fcntl.h> | |
17 #include "protos.h" | |
18 | |
19 int | |
1
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
20 elf32_open(const char *filename, int flags, Elf32_Ehdr *ehdr) |
0 | 21 { |
22 int fd; | |
23 | |
24 fd = open(filename, flags); | |
25 if (fd == -1) | |
26 { | |
27 perror ("open"); | |
28 return -1; | |
29 } | |
30 | |
31 if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr)) | |
32 { | |
33 perror ("reading header"); | |
34 close(fd); | |
35 return -1; | |
36 } | |
37 | |
38 if (0 != memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || | |
1
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
39 ehdr->e_ident[EI_CLASS] != ELFCLASS32 || |
0 | 40 ehdr->e_ident[EI_DATA] != ELFDATA2 || |
41 ehdr->e_ident[EI_VERSION] != EV_CURRENT) | |
42 { | |
43 fprintf(stderr, | |
44 #ifdef WORDS_BIGENDIAN | |
45 "`%s' probably isn't a %d-bit MSB-first ELF file.\n", | |
46 #else /* not WORD_BIGENDIAN */ | |
47 "`%s' probably isn't a %d-bit LSB-first ELF file.\n", | |
48 #endif /* not WORD_BIGENDIAN */ | |
1
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
49 filename, 32); |
0 | 50 close(fd); |
51 errno = ENOEXEC; /* Hm, is this the best errno code to use? */ | |
52 return -1; | |
53 } | |
54 | |
1
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
55 printf("32-bit ELF file\n"); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
56 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
57 if (ehdr->e_phentsize != sizeof(Elf32_Phdr)) |
0 | 58 { |
1
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
59 fprintf(stderr, "section size was read as %d, not %lu!\n", |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
60 ehdr->e_phentsize, sizeof(Elf32_Phdr)); |
0 | 61 close(fd); |
62 return -1; | |
63 } | |
64 return fd; | |
65 } | |
66 | |
67 int | |
1
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
68 elf64_open(const char *filename, int flags, Elf64_Ehdr *ehdr) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
69 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
70 int fd; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
71 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
72 fd = open(filename, flags); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
73 if (fd == -1) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
74 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
75 perror ("open"); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
76 return -1; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
77 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
78 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
79 if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr)) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
80 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
81 perror ("reading header"); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
82 close(fd); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
83 return -1; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
84 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
85 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
86 if (0 != memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
87 ehdr->e_ident[EI_CLASS] != ELFCLASS64 || |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
88 ehdr->e_ident[EI_DATA] != ELFDATA2 || |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
89 ehdr->e_ident[EI_VERSION] != EV_CURRENT) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
90 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
91 fprintf(stderr, |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
92 #ifdef WORDS_BIGENDIAN |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
93 "`%s' probably isn't a %d-bit MSB-first ELF file.\n", |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
94 #else /* not WORD_BIGENDIAN */ |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
95 "`%s' probably isn't a %d-bit LSB-first ELF file.\n", |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
96 #endif /* not WORD_BIGENDIAN */ |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
97 filename, 64); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
98 close(fd); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
99 errno = ENOEXEC; /* Hm, is this the best errno code to use? */ |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
100 return -1; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
101 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
102 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
103 printf("64-bit ELF file\n"); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
104 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
105 if (ehdr->e_phentsize != sizeof(Elf64_Phdr)) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
106 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
107 fprintf(stderr, "section size was read as %d, not %lu!\n", |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
108 ehdr->e_phentsize, sizeof(Elf64_Phdr)); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
109 close(fd); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
110 return -1; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
111 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
112 return fd; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
113 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
114 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
115 int |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
116 elf32_find_dynamic_section(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
117 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
118 int i; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
119 if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
120 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
121 perror ("positioning for sections"); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
122 return 1; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
123 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
124 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
125 for (i = 0; i < ehdr->e_phnum; i++) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
126 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
127 if (read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr)) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
128 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
129 perror ("reading section header"); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
130 return 1; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
131 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
132 if (phdr->p_type == PT_DYNAMIC) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
133 break; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
134 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
135 if (i == ehdr->e_phnum) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
136 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
137 fprintf (stderr, "No dynamic section found.\n"); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
138 return 2; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
139 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
140 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
141 if (0 == phdr->p_filesz) |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
142 { |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
143 fprintf (stderr, "Length of dynamic section is zero.\n"); |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
144 return 3; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
145 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
146 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
147 return 0; |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
148 } |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
149 |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
150 int |
bbbfb3f97919
implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
151 elf64_find_dynamic_section(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdr) |
0 | 152 { |
153 int i; | |
154 if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1) | |
155 { | |
156 perror ("positioning for sections"); | |
157 return 1; | |
158 } | |
159 | |
160 for (i = 0; i < ehdr->e_phnum; i++) | |
161 { | |
162 if (read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr)) | |
163 { | |
164 perror ("reading section header"); | |
165 return 1; | |
166 } | |
167 if (phdr->p_type == PT_DYNAMIC) | |
168 break; | |
169 } | |
170 if (i == ehdr->e_phnum) | |
171 { | |
172 fprintf (stderr, "No dynamic section found.\n"); | |
173 return 2; | |
174 } | |
175 | |
176 if (0 == phdr->p_filesz) | |
177 { | |
178 fprintf (stderr, "Length of dynamic section is zero.\n"); | |
179 return 3; | |
180 } | |
181 | |
182 return 0; | |
183 } | |
184 | |
185 void | |
186 elf_close(int fd) | |
187 { | |
188 close(fd); | |
189 } | |
190 | |
191 const char * | |
192 elf_tagname(int tag) | |
193 { | |
194 switch (tag) { | |
195 case DT_RPATH: | |
196 return "RPATH"; | |
197 break; | |
198 #if defined(DT_RUNPATH) | |
199 case DT_RUNPATH: | |
200 return "RUNPATH"; | |
201 break; | |
202 #endif /* DT_RUNPATH */ | |
203 } | |
204 return "UNKNOWN"; | |
205 } | |
206 | |
207 int | |
208 elf_dynpath_tag(int tag) | |
209 { | |
210 return ( tag == DT_RPATH | |
211 #if defined(DT_RUNPATH) | |
212 || tag == DT_RUNPATH | |
213 #endif /* DT_RUNPATH */ | |
214 ); | |
215 } |