aboutsummaryrefslogtreecommitdiff
path: root/ld/plugin.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-02-06 09:05:35 -0800
committerH.J. Lu <hjl.tools@gmail.com>2015-02-06 09:05:57 -0800
commit2aec968d4df313f893f239a1a69aef2392a16b85 (patch)
treec6545b73df74130e9c2ff0a078c7af099ee1c6c7 /ld/plugin.c
parentd6c146e9ea09e050e6f05fa00312de3fe763e811 (diff)
downloadbinutils-2aec968d4df313f893f239a1a69aef2392a16b85.zip
binutils-2aec968d4df313f893f239a1a69aef2392a16b85.tar.gz
binutils-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.c89
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;