1 /* Copyright (C) 2021 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
22 #include <sys/types.h>
25 #include <unistd.h> // for close();
28 #include "Data_window.h"
37 Data_window::Data_window (char *file_name)
39 Dprintf (DEBUG_DATA_WINDOW, NTXT ("Data_window:%d %s\n"), (int) __LINE__, STR (file_name));
40 page_size = sysconf (_SC_PAGESIZE);
41 need_swap_endian = false;
48 fname = dbe_strdup (file_name);
55 fd = open64 (fname, O_RDONLY);
58 fsize = lseek (fd, 0, SEEK_END);
70 base = (void*) mmap (NULL, (size_t) fsize, PROT_READ, MAP_PRIVATE, fd, 0);
73 if (base == MAP_FAILED)
86 Data_window::bind (int64_t file_offset, int64_t minSize)
89 span.length = fsize - file_offset;
90 span.offset = file_offset;
91 return bind (&span, minSize);
95 Data_window::bind (Span *span, int64_t minSize)
97 // Do any necessary mapping to access the desired span of data
98 // and return a pointer to the first byte.
99 Dprintf (DEBUG_DATA_WINDOW, NTXT ("Data_window:bind:%d offset=%llx:%lld minSize=%lld \n"),
100 (int) __LINE__, (long long) span->offset, (long long) span->length, (long long) minSize);
101 if (minSize == 0 || span->length < minSize)
104 if (span->offset < woffset || span->offset + minSize > woffset + wsize)
107 if (span->offset + minSize > fsize)
113 myfd = open64 (fname, O_RDONLY, 0);
117 bool remap_failed = true;
122 munmap ((caddr_t) base, (size_t) wsize);
125 woffset = span->offset & ~(page_size - 1);
126 wsize = page_size * ((MINBUFSIZE + page_size - 1) / page_size);
127 if (span->offset + minSize > woffset + wsize)
129 wsize += page_size * ((span->offset + minSize -
130 woffset - wsize + page_size - 1) / page_size);
131 base = (void *) mmap (0, (size_t) wsize, PROT_READ, MAP_SHARED, fd, woffset);
132 if (base == MAP_FAILED)
137 remap_failed = (base == NULL);
141 remap_failed = false;
142 woffset = span->offset & ~(WIN_ALIGN - 1);
143 wsize = minSize + (span->offset % WIN_ALIGN);
144 if (wsize < MINBUFSIZE)
148 if (basesize < wsize)
149 { // Need to realloc 'base'
152 base = (void *) malloc (basesize);
153 Dprintf (DEBUG_DATA_WINDOW,
154 NTXT ("Data_window:bind:%d realloc basesize=%llx woffset=%lld \n"),
155 (int) __LINE__, (long long) basesize, (long long) woffset);
162 if (wsize > fsize - woffset)
163 wsize = fsize - woffset;
164 off_t woff = (off_t) woffset;
165 if (base == NULL || woff != lseek (myfd, woff, SEEK_SET)
166 || wsize != read_from_file (myfd, base, wsize))
178 return (void *) ((char*) base + span->offset - woffset);
182 Data_window::get_data (int64_t offset, int64_t size, void *datap)
186 void *buf = bind (offset, size);
189 if (datap == NULL && !mmap_on_file)
190 // Can be remmaped or reallocated. Need to make a copy
191 datap = (void *) malloc (size);
194 memcpy (datap, buf, (size_t) size);
200 Data_window::~Data_window ()
208 munmap ((caddr_t) base, (size_t) wsize);
215 Data_window::get_buf_size ()
217 int64_t sz = MINBUFSIZE;
226 Data_window::copy_to_file (int f, int64_t offset, int64_t size)
228 long long bsz = get_buf_size ();
229 for (long long n = 0; n < size;)
231 long long sz = (bsz <= (size - n)) ? bsz : (size - n);
232 void *b = bind (offset + n, sz);
235 long long len = write (f, b, sz);