1 /* $NetBSD: libelf_open.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
4 * Copyright (c) 2006,2008-2011 Joseph Koshy
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #if HAVE_NBTOOL_CONFIG_H
30 # include "nbtool_config.h"
33 #include <sys/types.h>
48 __RCSID("$NetBSD: libelf_open.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
49 ELFTC_VCSID("Id: libelf_open.c 2932 2013-03-30 01:26:04Z jkoshy ");
51 #define _LIBELF_INITSIZE (64*1024)
54 * Read from a device file, pipe or socket.
57 _libelf_read_special_file(int fd
, size_t *fsz
)
61 unsigned char *buf
, *t
;
65 bufsz
= _LIBELF_INITSIZE
;
66 if ((buf
= malloc(bufsz
)) == NULL
)
70 * Read data from the file descriptor till we reach EOF, or
71 * till an error is encountered.
74 /* Check if we need to expand the data buffer. */
75 if (datasz
== bufsz
) {
77 if ((t
= realloc(buf
, bufsz
)) == NULL
)
83 readsz
= bufsz
- datasz
;
85 if ((readsz
= read(fd
, t
, readsz
)) <= 0)
88 } while (datasz
< bufsz
);
93 LIBELF_SET_ERROR(IO
, errno
);
100 * Free up extra buffer space.
102 if (bufsz
> datasz
) {
104 if ((t
= realloc(buf
, datasz
)) == NULL
)
107 } else { /* Zero bytes read. */
108 LIBELF_SET_ERROR(ARGUMENT
, 0);
118 LIBELF_SET_ERROR(RESOURCE
, 0);
126 * Read the contents of the file referenced by the file descriptor
131 _libelf_open_object(int fd
, Elf_Cmd c
, int reporterror
)
140 assert(c
== ELF_C_READ
|| c
== ELF_C_RDWR
|| c
== ELF_C_WRITE
);
142 if (fstat(fd
, &sb
) < 0) {
143 LIBELF_SET_ERROR(IO
, errno
);
148 fsize
= (size_t) sb
.st_size
;
151 * Reject unsupported file types.
153 if (!S_ISREG(mode
) && !S_ISCHR(mode
) && !S_ISFIFO(mode
) &&
155 LIBELF_SET_ERROR(ARGUMENT
, 0);
160 * For ELF_C_WRITE mode, allocate and return a descriptor.
162 if (c
== ELF_C_WRITE
) {
163 if ((e
= _libelf_allocate_elf()) != NULL
) {
164 _libelf_init_elf(e
, ELF_K_ELF
);
165 e
->e_byteorder
= _libelf_host_byteorder();
169 e
->e_flags
|= LIBELF_F_SPECIAL_FILE
;
177 * ELF_C_READ and ELF_C_RDWR mode.
184 * Reject zero length files.
187 LIBELF_SET_ERROR(ARGUMENT
, 0);
193 * Always map regular files in with 'PROT_READ'
196 * For objects opened in ELF_C_RDWR mode, when
197 * elf_update(3) is called, we remove this mapping,
198 * write file data out using write(2), and map the new
201 m
= mmap(NULL
, fsize
, PROT_READ
, MAP_PRIVATE
, fd
, (off_t
) 0);
206 flags
= LIBELF_F_RAWFILE_MMAP
;
210 * Fallback to a read() if the call to mmap() failed,
211 * or if mmap() is not available.
214 if ((m
= malloc(fsize
)) == NULL
) {
215 LIBELF_SET_ERROR(RESOURCE
, 0);
219 if (read(fd
, m
, fsize
) != (ssize_t
) fsize
) {
220 LIBELF_SET_ERROR(IO
, errno
);
225 flags
= LIBELF_F_RAWFILE_MALLOC
;
227 } else if ((m
= _libelf_read_special_file(fd
, &fsize
)) != NULL
)
228 flags
= LIBELF_F_RAWFILE_MALLOC
| LIBELF_F_SPECIAL_FILE
;
232 if ((e
= _libelf_memory(m
, fsize
, reporterror
)) == NULL
) {
233 assert((flags
& LIBELF_F_RAWFILE_MALLOC
) ||
234 (flags
& LIBELF_F_RAWFILE_MMAP
));
235 if (flags
& LIBELF_F_RAWFILE_MALLOC
)
239 (void) munmap(m
, fsize
);
244 /* ar(1) archives aren't supported in RDWR mode. */
245 if (c
== ELF_C_RDWR
&& e
->e_kind
== ELF_K_AR
) {
247 LIBELF_SET_ERROR(ARGUMENT
, 0);