|
1 /* |
|
2 * input.c - low-level input for libelf. |
|
3 * Copyright (C) 1995 - 2001, 2005 Michael Riepe |
|
4 * |
|
5 * This library is free software; you can redistribute it and/or |
|
6 * modify it under the terms of the GNU Library General Public |
|
7 * License as published by the Free Software Foundation; either |
|
8 * version 2 of the License, or (at your option) any later version. |
|
9 * |
|
10 * This library is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 * Library General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU Library General Public |
|
16 * License along with this library; if not, write to the Free Software |
|
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
18 */ |
|
19 |
|
20 #include <private.h> |
|
21 |
|
22 #ifndef lint |
|
23 static const char rcsid[] = "@(#) $Id: input.c,v 1.10 2005/10/20 21:08:02 michael Exp $"; |
|
24 #endif /* lint */ |
|
25 |
|
26 #include <errno.h> |
|
27 |
|
28 #if HAVE_MMAP |
|
29 #include <sys/mman.h> |
|
30 #endif /* HAVE_MMAP */ |
|
31 |
|
32 static int |
|
33 xread(int fd, char *buffer, size_t len) { |
|
34 size_t done = 0; |
|
35 size_t n; |
|
36 |
|
37 while (done < len) { |
|
38 n = read(fd, buffer + done, len - done); |
|
39 if (n == 0) { |
|
40 /* premature end of file */ |
|
41 return -1; |
|
42 } |
|
43 else if (n != (size_t)-1) { |
|
44 /* some bytes read, continue */ |
|
45 done += n; |
|
46 } |
|
47 else if (errno != EAGAIN && errno != EINTR) { |
|
48 /* real error */ |
|
49 return -1; |
|
50 } |
|
51 } |
|
52 return 0; |
|
53 } |
|
54 |
|
55 void* |
|
56 _elf_read(Elf *elf, void *buffer, size_t off, size_t len) { |
|
57 void *tmp; |
|
58 |
|
59 elf_assert(elf); |
|
60 elf_assert(elf->e_magic == ELF_MAGIC); |
|
61 elf_assert(off >= 0 && off + len <= elf->e_size); |
|
62 if (elf->e_disabled) { |
|
63 seterr(ERROR_FDDISABLED); |
|
64 } |
|
65 else if (len) { |
|
66 off += elf->e_base; |
|
67 if (lseek(elf->e_fd, (off_t)off, SEEK_SET) != (off_t)off) { |
|
68 seterr(ERROR_IO_SEEK); |
|
69 } |
|
70 else if (!(tmp = buffer) && !(tmp = malloc(len))) { |
|
71 seterr(ERROR_IO_2BIG); |
|
72 } |
|
73 else if (xread(elf->e_fd, tmp, len)) { |
|
74 seterr(ERROR_IO_READ); |
|
75 if (tmp != buffer) { |
|
76 free(tmp); |
|
77 } |
|
78 } |
|
79 else { |
|
80 return tmp; |
|
81 } |
|
82 } |
|
83 return NULL; |
|
84 } |
|
85 |
|
86 void* |
|
87 _elf_mmap(Elf *elf) { |
|
88 #if HAVE_MMAP |
|
89 void *tmp; |
|
90 |
|
91 elf_assert(elf); |
|
92 elf_assert(elf->e_magic == ELF_MAGIC); |
|
93 elf_assert(elf->e_base == 0); |
|
94 if (elf->e_disabled) { |
|
95 seterr(ERROR_FDDISABLED); |
|
96 } |
|
97 else if (elf->e_size) { |
|
98 tmp = (void*)mmap(0, elf->e_size, PROT_READ | PROT_WRITE, |
|
99 MAP_PRIVATE, elf->e_fd, 0); |
|
100 if (tmp != (void*)-1) { |
|
101 return tmp; |
|
102 } |
|
103 } |
|
104 #endif /* HAVE_MMAP */ |
|
105 return NULL; |
|
106 } |