]> Git Repo - binutils.git/blob - gprofng/src/Data_window.cc
Automatic date update in version.in
[binutils.git] / gprofng / src / Data_window.cc
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2    Contributed by Oracle.
3
4    This file is part of GNU Binutils.
5
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)
9    any later version.
10
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.
15
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.  */
20
21 #include "config.h"
22 #include <sys/types.h>
23 #include <sys/mman.h>
24 #include <fcntl.h>
25 #include <unistd.h>     //  for close();
26
27 #include "util.h"
28 #include "Data_window.h"
29 #include "debug.h"
30
31 enum
32 {
33   MINBUFSIZE    = 1 << 16,
34   WIN_ALIGN     = 8
35 };
36
37 Data_window::Data_window (char *file_name)
38 {
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;
42   opened = false;
43   fsize = 0;
44   base = NULL;
45   woffset = 0;
46   wsize = 0;
47   basesize = 0;
48   fname = dbe_strdup (file_name);
49   mmap_on_file = false;
50   use_mmap = false;
51 #if DEBUG
52   if (DBE_USE_MMAP)
53     use_mmap = true;
54 #endif /* DEBUG */
55   fd = open64 (fname, O_RDONLY);
56   if (fd == -1)
57     return;
58   fsize = lseek (fd, 0, SEEK_END);
59   if (fsize == 0)
60     {
61       close (fd);
62       fd = -1;
63       return;
64     }
65   opened = true;
66   if (use_mmap)
67     {
68       if (fsize != -1)
69         {
70           base = (void*) mmap (NULL, (size_t) fsize, PROT_READ, MAP_PRIVATE, fd, 0);
71           close (fd);
72           fd = -1;
73           if (base == MAP_FAILED)
74             {
75               base = NULL;
76               use_mmap = false;
77               return;
78             }
79           mmap_on_file = true;
80           wsize = fsize;
81         }
82     }
83 }
84
85 void *
86 Data_window::bind (int64_t file_offset, int64_t minSize)
87 {
88   Span span;
89   span.length = fsize - file_offset;
90   span.offset = file_offset;
91   return bind (&span, minSize);
92 }
93
94 void *
95 Data_window::bind (Span *span, int64_t minSize)
96 {
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)
102     return NULL;
103
104   if (span->offset < woffset || span->offset + minSize > woffset + wsize)
105     {
106       // Remap the window
107       if (span->offset + minSize > fsize)
108         return NULL;
109       int myfd = fd;
110       if (myfd == -1)
111         {
112           if (fname)
113             myfd = open64 (fname, O_RDONLY, 0);
114           if (myfd == -1)
115             return NULL;
116         }
117       bool remap_failed = true;
118       if (use_mmap)
119         {
120           if (base)
121             {
122               munmap ((caddr_t) base, (size_t) wsize);
123               base = NULL;
124             }
125           woffset = span->offset & ~(page_size - 1);
126           wsize = page_size * ((MINBUFSIZE + page_size - 1) / page_size);
127           if (span->offset + minSize > woffset + wsize)
128             // Extend a window
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)
133             {
134               base = NULL;
135               use_mmap = false;
136             }
137           remap_failed = (base == NULL);
138         }
139       if (remap_failed)
140         {
141           remap_failed = false;
142           woffset = span->offset & ~(WIN_ALIGN - 1);
143           wsize = minSize + (span->offset % WIN_ALIGN);
144           if (wsize < MINBUFSIZE)
145             wsize = MINBUFSIZE;
146           if (wsize > fsize)
147             wsize = fsize;
148           if (basesize < wsize)
149             { // Need to realloc 'base'
150               free (base);
151               basesize = wsize;
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);
156               if (base == NULL)
157                 {
158                   basesize = 0;
159                   remap_failed = true;
160                 }
161             }
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))
167             remap_failed = true;
168         }
169       if (fd == -1)
170         close (myfd);
171       if (remap_failed)
172         {
173           woffset = 0;
174           wsize = 0;
175           return NULL;
176         }
177     }
178   return (void *) ((char*) base + span->offset - woffset);
179 }
180
181 void *
182 Data_window::get_data (int64_t offset, int64_t size, void *datap)
183 {
184   if (size <= 0)
185     return NULL;
186   void *buf = bind (offset, size);
187   if (buf == NULL)
188     return NULL;
189   if (datap == NULL && !mmap_on_file)
190     // Can be remmaped or reallocated. Need to make a copy
191     datap = (void *) malloc (size);
192   if (datap)
193     {
194       memcpy (datap, buf, (size_t) size);
195       return datap;
196     }
197   return buf;
198 }
199
200 Data_window::~Data_window ()
201 {
202   free (fname);
203   if (fd != -1)
204     close (fd);
205   if (base)
206     {
207       if (use_mmap)
208         munmap ((caddr_t) base, (size_t) wsize);
209       else
210         free (base);
211     }
212 }
213
214 int64_t
215 Data_window::get_buf_size ()
216 {
217   int64_t sz = MINBUFSIZE;
218   if (sz < basesize)
219     sz = basesize;
220   if (sz > fsize)
221     sz = fsize;
222   return sz;
223 }
224
225 int64_t
226 Data_window::copy_to_file (int f, int64_t offset, int64_t size)
227 {
228   long long bsz = get_buf_size ();
229   for (long long n = 0; n < size;)
230     {
231       long long sz = (bsz <= (size - n)) ? bsz : (size - n);
232       void *b = bind (offset + n, sz);
233       if (b == NULL)
234         return n;
235       long long len = write (f, b, sz);
236       if (len <= 0)
237         return n;
238       n += len;
239     }
240   return size;
241 }
This page took 0.037925 seconds and 4 git commands to generate.