00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <private.h>
00025
00026 #ifndef lint
00027 static const char rcsid[] = "@(#) $Id: begin.c,v 1.1.1.1 2005/10/21 19:00:00 marcel Exp $";
00028 #endif
00029
00030 #if HAVE_AR_H
00031 #include <ar.h>
00032 #else
00033
00034 #define ARMAG "!<arch>\n"
00035 #define SARMAG 8
00036
00037 struct ar_hdr {
00038 char ar_name[16];
00039 char ar_date[12];
00040 char ar_uid[6];
00041 char ar_gid[6];
00042 char ar_mode[8];
00043 char ar_size[10];
00044 char ar_fmag[2];
00045 };
00046
00047 #define ARFMAG "`\n"
00048
00049 #endif
00050
00051 static const Elf _elf_init = INIT_ELF;
00052 static const char fmag[] = ARFMAG;
00053
00054 static unsigned long
00055 getnum(const char *str, size_t len, int base, int *err) {
00056 unsigned long result = 0;
00057
00058 while (len && *str == ' ') {
00059 str++; len--;
00060 }
00061 while (len && *str >= '0' && (*str - '0') < base) {
00062 result = base * result + *str++ - '0'; len--;
00063 }
00064 while (len && *str == ' ') {
00065 str++; len--;
00066 }
00067 if (len) {
00068 *err = len;
00069 }
00070 return result;
00071 }
00072
00073 static void
00074 _elf_init_ar(Elf *elf) {
00075 struct ar_hdr *hdr;
00076 size_t offset;
00077 size_t size;
00078 int err = 0;
00079
00080 elf->e_kind = ELF_K_AR;
00081 elf->e_idlen = SARMAG;
00082 elf->e_off = SARMAG;
00083
00084
00085 offset = SARMAG;
00086 while (!elf->e_strtab && offset + sizeof(*hdr) <= elf->e_size) {
00087 hdr = (struct ar_hdr*)(elf->e_data + offset);
00088 if (memcmp(hdr->ar_fmag, fmag, sizeof(fmag) - 1)) {
00089 break;
00090 }
00091 if (hdr->ar_name[0] != '/') {
00092 break;
00093 }
00094 size = getnum(hdr->ar_size, sizeof(hdr->ar_size), 10, &err);
00095 if (err || !size) {
00096 break;
00097 }
00098 offset += sizeof(*hdr);
00099 if (offset + size > elf->e_size) {
00100 break;
00101 }
00102 if (hdr->ar_name[1] == '/' && hdr->ar_name[2] == ' ') {
00103 elf->e_strtab = elf->e_data + offset;
00104 elf->e_strlen = size;
00105 break;
00106 }
00107 if (elf->e_symtab || hdr->ar_name[1] != ' ') {
00108 break;
00109 }
00110 elf->e_symtab = elf->e_data + offset;
00111 elf->e_symlen = size;
00112 offset += size + (size & 1);
00113 }
00114 }
00115
00116 static Elf_Arhdr*
00117 _elf_arhdr(Elf *arf) {
00118 struct ar_hdr *hdr;
00119 Elf_Arhdr *arhdr;
00120 size_t namelen;
00121 size_t tmp;
00122 char *name;
00123 int err = 0;
00124
00125 if (arf->e_off == arf->e_size) {
00126
00127 return NULL;
00128 }
00129 if (arf->e_off < 0 || arf->e_off > arf->e_size) {
00130 seterr(ERROR_OUTSIDE);
00131 return NULL;
00132 }
00133 if (arf->e_off + sizeof(*hdr) > arf->e_size) {
00134 seterr(ERROR_TRUNC_ARHDR);
00135 return NULL;
00136 }
00137 elf_assert(arf->e_data != NULL);
00138 hdr = (struct ar_hdr*)(arf->e_data + arf->e_off);
00139 if (memcmp(hdr->ar_fmag, fmag, sizeof(fmag) - 1)) {
00140 seterr(ERROR_ARFMAG);
00141 return NULL;
00142 }
00143
00144 name = hdr->ar_name;
00145 for (namelen = sizeof(hdr->ar_name); namelen > 0; namelen--) {
00146 if (name[namelen - 1] != ' ') {
00147 break;
00148 }
00149 }
00150 if (name[0] == '/') {
00151 if (name[1] >= '0' && name[1] <= '9') {
00152 if (!arf->e_strtab) {
00153 seterr(ERROR_ARSTRTAB);
00154 return NULL;
00155 }
00156 tmp = getnum(&name[1], namelen - 1, 10, &err);
00157 if (err) {
00158 seterr(ERROR_ARSPECIAL);
00159 return NULL;
00160 }
00161 if (tmp < 0 || tmp >= arf->e_strlen) {
00162 seterr(ERROR_ARSTRTAB);
00163 return NULL;
00164 }
00165 for (namelen = tmp; namelen < arf->e_strlen; namelen++) {
00166 if (arf->e_strtab[namelen] == '/') {
00167 break;
00168 }
00169 }
00170 if (namelen == arf->e_strlen) {
00171 seterr(ERROR_ARSTRTAB);
00172 return NULL;
00173 }
00174 name = arf->e_strtab + tmp;
00175 namelen -= tmp;
00176 }
00177 else if (namelen != 1 && !(namelen == 2 && name[1] == '/')) {
00178 seterr(ERROR_ARSPECIAL);
00179 return NULL;
00180 }
00181 }
00182 else if (namelen > 0 && name[namelen - 1] == '/') {
00183 namelen--;
00184 }
00185
00186
00187
00188
00189
00190
00191 if (!(arhdr = (Elf_Arhdr*)malloc(sizeof(*arhdr) +
00192 sizeof(hdr->ar_name) + namelen + 2))) {
00193 seterr(ERROR_MEM_ARHDR);
00194 return NULL;
00195 }
00196
00197 arhdr->ar_name = NULL;
00198 arhdr->ar_rawname = (char*)(arhdr + 1);
00199 arhdr->ar_date = getnum(hdr->ar_date, sizeof(hdr->ar_date), 10, &err);
00200 arhdr->ar_uid = getnum(hdr->ar_uid, sizeof(hdr->ar_uid), 10, &err);
00201 arhdr->ar_gid = getnum(hdr->ar_gid, sizeof(hdr->ar_gid), 10, &err);
00202 arhdr->ar_mode = getnum(hdr->ar_mode, sizeof(hdr->ar_mode), 8, &err);
00203 arhdr->ar_size = getnum(hdr->ar_size, sizeof(hdr->ar_size), 10, &err);
00204 if (err) {
00205 free(arhdr);
00206 seterr(ERROR_ARHDR);
00207 return NULL;
00208 }
00209 if (arf->e_off + sizeof(struct ar_hdr) + arhdr->ar_size > arf->e_size) {
00210 free(arhdr);
00211 seterr(ERROR_TRUNC_MEMBER);
00212 return NULL;
00213 }
00214
00215 memcpy(arhdr->ar_rawname, hdr->ar_name, sizeof(hdr->ar_name));
00216 arhdr->ar_rawname[sizeof(hdr->ar_name)] = '\0';
00217
00218 if (namelen) {
00219 arhdr->ar_name = arhdr->ar_rawname + sizeof(hdr->ar_name) + 1;
00220 memcpy(arhdr->ar_name, name, namelen);
00221 arhdr->ar_name[namelen] = '\0';
00222 }
00223
00224 return arhdr;
00225 }
00226
00227 static void
00228 _elf_check_type(Elf *elf, size_t size) {
00229 elf->e_idlen = size;
00230 if (size >= EI_NIDENT && !memcmp(elf->e_data, ELFMAG, SELFMAG)) {
00231 elf->e_kind = ELF_K_ELF;
00232 elf->e_idlen = EI_NIDENT;
00233 elf->e_class = elf->e_data[EI_CLASS];
00234 elf->e_encoding = elf->e_data[EI_DATA];
00235 elf->e_version = elf->e_data[EI_VERSION];
00236 }
00237 else if (size >= SARMAG && !memcmp(elf->e_data, ARMAG, SARMAG)) {
00238 _elf_init_ar(elf);
00239 }
00240 }
00241
00242 Elf*
00243 elf_begin(int fd, Elf_Cmd cmd, Elf *ref) {
00244 Elf_Arhdr *arhdr = NULL;
00245 size_t size = 0;
00246 off_t off;
00247 Elf *elf;
00248
00249 elf_assert(_elf_init.e_magic == ELF_MAGIC);
00250 if (_elf_version == EV_NONE) {
00251 seterr(ERROR_VERSION_UNSET);
00252 return NULL;
00253 }
00254 else if (cmd == ELF_C_NULL) {
00255 return NULL;
00256 }
00257 else if (cmd == ELF_C_WRITE) {
00258 ref = NULL;
00259 }
00260 else if (cmd != ELF_C_READ && cmd != ELF_C_RDWR) {
00261 seterr(ERROR_INVALID_CMD);
00262 return NULL;
00263 }
00264 else if (ref) {
00265 elf_assert(ref->e_magic == ELF_MAGIC);
00266 if (!ref->e_readable || (cmd == ELF_C_RDWR && !ref->e_writable)) {
00267 seterr(ERROR_CMDMISMATCH);
00268 return NULL;
00269 }
00270 if (ref->e_kind != ELF_K_AR) {
00271 ref->e_count++;
00272 return ref;
00273 }
00274 if (cmd == ELF_C_RDWR) {
00275 seterr(ERROR_MEMBERWRITE);
00276 return NULL;
00277 }
00278 if (ref->e_memory) {
00279 fd = ref->e_fd;
00280 }
00281 else if (fd != ref->e_fd) {
00282 seterr(ERROR_FDMISMATCH);
00283 return NULL;
00284 }
00285 if (!(arhdr = _elf_arhdr(ref))) {
00286 return NULL;
00287 }
00288 size = arhdr->ar_size;
00289 }
00290 else if ((off = lseek(fd, (off_t)0, SEEK_END)) == (off_t)-1 || (size = off) != off) {
00291 seterr(ERROR_IO_GETSIZE);
00292 return NULL;
00293 }
00294
00295 if (!(elf = (Elf*)malloc(sizeof(Elf)))) {
00296 seterr(ERROR_MEM_ELF);
00297 return NULL;
00298 }
00299 *elf = _elf_init;
00300 elf->e_fd = fd;
00301 elf->e_parent = ref;
00302 elf->e_size = elf->e_dsize = size;
00303
00304 if (cmd != ELF_C_READ) {
00305 elf->e_writable = 1;
00306 }
00307 if (cmd != ELF_C_WRITE) {
00308 elf->e_readable = 1;
00309 }
00310 else {
00311 return elf;
00312 }
00313
00314 if (ref) {
00315 size_t offset = ref->e_off + sizeof(struct ar_hdr);
00316 Elf *xelf;
00317
00318 elf_assert(arhdr);
00319 elf->e_arhdr = arhdr;
00320 elf->e_base = ref->e_base + offset;
00321
00322
00323
00324
00325
00326
00327
00328
00329 for (xelf = ref->e_members; xelf; xelf = xelf->e_link) {
00330 elf_assert(xelf->e_parent == ref);
00331 if (xelf->e_base == elf->e_base) {
00332 free(arhdr);
00333 free(elf);
00334 xelf->e_count++;
00335 return xelf;
00336 }
00337 }
00338 if (size == 0) {
00339 elf->e_data = NULL;
00340 }
00341 else if (ref->e_data == ref->e_rawdata) {
00342 elf_assert(!ref->e_cooked);
00343
00344
00345
00346 elf->e_data = elf->e_rawdata = ref->e_data + offset;
00347 }
00348 else {
00349 elf_assert(!ref->e_memory);
00350 elf->e_data = ref->e_data + offset;
00351
00352
00353
00354
00355
00356
00357 if (!ref->e_cooked) {
00358 ref->e_cooked = 1;
00359 }
00360 else if (!_elf_read(ref, elf->e_data, offset, size)) {
00361 free(arhdr);
00362 free(elf);
00363 return NULL;
00364 }
00365 }
00366 elf->e_next = offset + size + (size & 1);
00367 elf->e_disabled = ref->e_disabled;
00368 elf->e_memory = ref->e_memory;
00369
00370 elf->e_link = ref->e_members;
00371 ref->e_members = elf;
00372 ref->e_count++;
00373
00374 ref->e_off = elf->e_next;
00375 }
00376 else if (size) {
00377 #if HAVE_MMAP
00378
00379
00380
00381 if (!elf->e_writable && (elf->e_data = _elf_mmap(elf))) {
00382 elf->e_unmap_data = 1;
00383 }
00384 else
00385 #endif
00386 if (!(elf->e_data = _elf_read(elf, NULL, 0, size))) {
00387 free(elf);
00388 return NULL;
00389 }
00390 }
00391
00392 _elf_check_type(elf, size);
00393 return elf;
00394 }
00395
00396 Elf*
00397 elf_memory(char *image, size_t size) {
00398 Elf *elf;
00399
00400 elf_assert(_elf_init.e_magic == ELF_MAGIC);
00401 if (_elf_version == EV_NONE) {
00402 seterr(ERROR_VERSION_UNSET);
00403 return NULL;
00404 }
00405 else if (size == 0 || image == NULL) {
00406
00407 return NULL;
00408 }
00409
00410 if (!(elf = (Elf*)malloc(sizeof(Elf)))) {
00411 seterr(ERROR_MEM_ELF);
00412 return NULL;
00413 }
00414 *elf = _elf_init;
00415 elf->e_size = elf->e_dsize = size;
00416 elf->e_data = elf->e_rawdata = image;
00417 elf->e_readable = 1;
00418 elf->e_disabled = 1;
00419 elf->e_memory = 1;
00420
00421 _elf_check_type(elf, size);
00422 return elf;
00423 }
00424
00425 #if __LIBELF64
00426
00427 int
00428 gelf_getclass(Elf *elf) {
00429 if (elf && elf->e_kind == ELF_K_ELF && valid_class(elf->e_class)) {
00430 return elf->e_class;
00431 }
00432 return ELFCLASSNONE;
00433 }
00434
00435 #endif