diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2015-02-06 09:05:35 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-02-06 09:05:57 -0800 |
commit | 2aec968d4df313f893f239a1a69aef2392a16b85 (patch) | |
tree | c6545b73df74130e9c2ff0a078c7af099ee1c6c7 /ld/plugin.c | |
parent | d6c146e9ea09e050e6f05fa00312de3fe763e811 (diff) | |
download | fsf-binutils-gdb-2aec968d4df313f893f239a1a69aef2392a16b85.zip fsf-binutils-gdb-2aec968d4df313f893f239a1a69aef2392a16b85.tar.gz fsf-binutils-gdb-2aec968d4df313f893f239a1a69aef2392a16b85.tar.bz2 |
Use mmap and cache the view buffer for get_view
This patch uses mmap if it is available and works. It also caches the
view buffer for get_view.
* configure.ac: Add AC_FUNC_MMAP.
* config.in: Regenerated.
* configure: Likewise.
* plugin.c: Include <sys/mman.h>.
(MAP_FAILED): New. Defined if not defined.
(PROT_READ): Likewise.
(MAP_PRIVATE): Likewise.
(view_buffer_t): New.
(plugin_input_file_t): Add view_buffer.
(get_view): Try mmap and cache the view buffer.
(plugin_maybe_claim): Initialize view_buffer.
Diffstat (limited to 'ld/plugin.c')
-rw-r--r-- | ld/plugin.c | 89 |
1 files changed, 70 insertions, 19 deletions
diff --git a/ld/plugin.c b/ld/plugin.c index ae0ac89..7ee45a2 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -32,6 +32,18 @@ #include "plugin.h" #include "plugin-api.h" #include "elf-bfd.h" +#if HAVE_MMAP +# include <sys/mman.h> +# ifndef MAP_FAILED +# define MAP_FAILED ((void *) -1) +# endif +# ifndef PROT_READ +# define PROT_READ 0 +# endif +# ifndef MAP_PRIVATE +# define MAP_PRIVATE 0 +# endif +#endif #include <errno.h> #if !(defined(errno) || defined(_MSC_VER) && defined(_INC_ERRNO)) extern int errno; @@ -76,11 +88,19 @@ typedef struct plugin bfd_boolean cleanup_done; } plugin_t; +typedef struct view_buffer +{ + char *addr; + size_t filesize; + off_t offset; +} view_buffer_t; + /* The internal version of struct ld_plugin_input_file with a BFD pointer. */ typedef struct plugin_input_file { bfd *abfd; + view_buffer_t view_buffer; char *name; int fd; off_t offset; @@ -475,35 +495,63 @@ get_input_file (const void *handle, struct ld_plugin_input_file *file) static enum ld_plugin_status get_view (const void *handle, const void **viewp) { - const plugin_input_file_t *input = handle; + plugin_input_file_t *input = (plugin_input_file_t *) handle; char *buffer; - size_t size; + size_t size = input->filesize; ASSERT (called_plugin); - if (lseek (input->fd, input->offset, SEEK_SET) < 0) - return LDPS_ERR; + /* FIXME: einfo should support %lld. */ + if ((off_t) size != input->filesize) + einfo (_("%P%F: unsupported input file size: %s (%ld bytes)\n"), + input->name, (long) input->filesize); - size = input->filesize; - buffer = bfd_alloc (input->abfd, size); - if (buffer == NULL) - return LDPS_ERR; - *viewp = buffer; + /* Check the cached view buffer. */ + if (input->view_buffer.addr != NULL + && input->view_buffer.filesize == size + && input->view_buffer.offset == input->offset) + { + *viewp = input->view_buffer.addr; + return LDPS_OK; + } + + input->view_buffer.filesize = size; + input->view_buffer.offset = input->offset; - do +#if HAVE_MMAP + buffer = mmap (NULL, size, PROT_READ, MAP_PRIVATE, input->fd, + input->offset); + if (buffer == MAP_FAILED) +#endif { - ssize_t got = read (input->fd, buffer, size); - if (got == 0) - break; - else if (got > 0) + char *p; + + if (lseek (input->fd, input->offset, SEEK_SET) < 0) + return LDPS_ERR; + + buffer = bfd_alloc (input->abfd, size); + if (buffer == NULL) + return LDPS_ERR; + + p = buffer; + do { - buffer += got; - size -= got; + ssize_t got = read (input->fd, p, size); + if (got == 0) + break; + else if (got > 0) + { + p += got; + size -= got; + } + else if (errno != EINTR) + return LDPS_ERR; } - else if (errno != EINTR) - return LDPS_ERR; + while (size > 0); } - while (size > 0); + + input->view_buffer.addr = buffer; + *viewp = buffer; return LDPS_OK; } @@ -951,6 +999,9 @@ plugin_maybe_claim (struct ld_plugin_input_file *file, bfd_get_error ()); input->abfd = abfd; + input->view_buffer.addr = NULL; + input->view_buffer.filesize = 0; + input->view_buffer.offset = 0; input->fd = file->fd; input->offset = file->offset; input->filesize = file->filesize; |