]> Git Repo - binutils.git/blob - gdb/target-memory.c
Update copyright year range in all GDB files.
[binutils.git] / gdb / target-memory.c
1 /* Parts of target interface that deal with accessing memory and memory-like
2    objects.
3
4    Copyright (C) 2006-2020 Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "defs.h"
22 #include "target.h"
23 #include "memory-map.h"
24
25 #include "gdbsupport/gdb_sys_time.h"
26 #include <algorithm>
27
28 static bool
29 compare_block_starting_address (const memory_write_request &a_req,
30                                 const memory_write_request &b_req)
31 {
32   return a_req.begin < b_req.begin;
33 }
34
35 /* Adds to RESULT all memory write requests from BLOCK that are
36    in [BEGIN, END) range.
37
38    If any memory request is only partially in the specified range,
39    that part of the memory request will be added.  */
40
41 static void
42 claim_memory (const std::vector<memory_write_request> &blocks,
43               std::vector<memory_write_request> *result,
44               ULONGEST begin,
45               ULONGEST end)
46 {
47   ULONGEST claimed_begin;
48   ULONGEST claimed_end;
49
50   for (const memory_write_request &r : blocks)
51     {
52       /* If the request doesn't overlap [BEGIN, END), skip it.  We
53          must handle END == 0 meaning the top of memory; we don't yet
54          check for R->end == 0, which would also mean the top of
55          memory, but there's an assertion in
56          target_write_memory_blocks which checks for that.  */
57
58       if (begin >= r.end)
59         continue;
60       if (end != 0 && end <= r.begin)
61         continue;
62
63       claimed_begin = std::max (begin, r.begin);
64       if (end == 0)
65         claimed_end = r.end;
66       else
67         claimed_end = std::min (end, r.end);
68
69       if (claimed_begin == r.begin && claimed_end == r.end)
70         result->push_back (r);
71       else
72         {
73           struct memory_write_request n = r;
74
75           n.begin = claimed_begin;
76           n.end = claimed_end;
77           n.data += claimed_begin - r.begin;
78
79           result->push_back (n);
80         }
81     }
82 }
83
84 /* Given a vector of struct memory_write_request objects in BLOCKS,
85    add memory requests for flash memory into FLASH_BLOCKS, and for
86    regular memory to REGULAR_BLOCKS.  */
87
88 static void
89 split_regular_and_flash_blocks (const std::vector<memory_write_request> &blocks,
90                                 std::vector<memory_write_request> *regular_blocks,
91                                 std::vector<memory_write_request> *flash_blocks)
92 {
93   struct mem_region *region;
94   CORE_ADDR cur_address;
95
96   /* This implementation runs in O(length(regions)*length(blocks)) time.
97      However, in most cases the number of blocks will be small, so this does
98      not matter.
99
100      Note also that it's extremely unlikely that a memory write request
101      will span more than one memory region, however for safety we handle
102      such situations.  */
103
104   cur_address = 0;
105   while (1)
106     {
107       std::vector<memory_write_request> *r;
108
109       region = lookup_mem_region (cur_address);
110       r = region->attrib.mode == MEM_FLASH ? flash_blocks : regular_blocks;
111       cur_address = region->hi;
112       claim_memory (blocks, r, region->lo, region->hi);
113
114       if (cur_address == 0)
115         break;
116     }
117 }
118
119 /* Given an ADDRESS, if BEGIN is non-NULL this function sets *BEGIN
120    to the start of the flash block containing the address.  Similarly,
121    if END is non-NULL *END will be set to the address one past the end
122    of the block containing the address.  */
123
124 static void
125 block_boundaries (CORE_ADDR address, CORE_ADDR *begin, CORE_ADDR *end)
126 {
127   struct mem_region *region;
128   unsigned blocksize;
129   CORE_ADDR offset_in_region;
130
131   region = lookup_mem_region (address);
132   gdb_assert (region->attrib.mode == MEM_FLASH);
133   blocksize = region->attrib.blocksize;
134
135   offset_in_region = address - region->lo;
136
137   if (begin)
138     *begin = region->lo + offset_in_region / blocksize * blocksize;
139   if (end)
140     *end = region->lo + (offset_in_region + blocksize - 1) / blocksize * blocksize;
141 }
142
143 /* Given the list of memory requests to be WRITTEN, this function
144    returns write requests covering each group of flash blocks which must
145    be erased.  */
146
147 static std::vector<memory_write_request>
148 blocks_to_erase (const std::vector<memory_write_request> &written)
149 {
150   std::vector<memory_write_request> result;
151
152   for (const memory_write_request &request : written)
153     {
154       CORE_ADDR begin, end;
155
156       block_boundaries (request.begin, &begin, 0);
157       block_boundaries (request.end - 1, 0, &end);
158
159       if (!result.empty () && result.back ().end >= begin)
160         result.back ().end = end;
161       else
162         result.emplace_back (begin, end);
163     }
164
165   return result;
166 }
167
168 /* Given ERASED_BLOCKS, a list of blocks that will be erased with
169    flash erase commands, and WRITTEN_BLOCKS, the list of memory
170    addresses that will be written, compute the set of memory addresses
171    that will be erased but not rewritten (e.g. padding within a block
172    which is only partially filled by "load").  */
173
174 static std::vector<memory_write_request>
175 compute_garbled_blocks (const std::vector<memory_write_request> &erased_blocks,
176                         const std::vector<memory_write_request> &written_blocks)
177 {
178   std::vector<memory_write_request> result;
179
180   unsigned j;
181   unsigned je = written_blocks.size ();
182
183   /* Look at each erased memory_write_request in turn, and
184      see what part of it is subsequently written to.
185
186      This implementation is O(length(erased) * length(written)).  If
187      the lists are sorted at this point it could be rewritten more
188      efficiently, but the complexity is not generally worthwhile.  */
189
190   for (const memory_write_request &erased_iter : erased_blocks)
191     {
192       /* Make a deep copy -- it will be modified inside the loop, but
193          we don't want to modify original vector.  */
194       struct memory_write_request erased = erased_iter;
195
196       for (j = 0; j != je;)
197         {
198           const memory_write_request *written = &written_blocks[j];
199
200           /* Now try various cases.  */
201
202           /* If WRITTEN is fully to the left of ERASED, check the next
203              written memory_write_request.  */
204           if (written->end <= erased.begin)
205             {
206               ++j;
207               continue;
208             }
209
210           /* If WRITTEN is fully to the right of ERASED, then ERASED
211              is not written at all.  WRITTEN might affect other
212              blocks.  */
213           if (written->begin >= erased.end)
214             {
215               result.push_back (erased);
216               goto next_erased;
217             }
218
219           /* If all of ERASED is completely written, we can move on to
220              the next erased region.  */
221           if (written->begin <= erased.begin
222               && written->end >= erased.end)
223             {
224               goto next_erased;
225             }
226
227           /* If there is an unwritten part at the beginning of ERASED,
228              then we should record that part and try this inner loop
229              again for the remainder.  */
230           if (written->begin > erased.begin)
231             {
232               result.emplace_back (erased.begin, written->begin);
233               erased.begin = written->begin;
234               continue;
235             }
236
237           /* If there is an unwritten part at the end of ERASED, we
238              forget about the part that was written to and wait to see
239              if the next write request writes more of ERASED.  We can't
240              push it yet.  */
241           if (written->end < erased.end)
242             {
243               erased.begin = written->end;
244               ++j;
245               continue;
246             }
247         }
248
249       /* If we ran out of write requests without doing anything about
250          ERASED, then that means it's really erased.  */
251       result.push_back (erased);
252
253     next_erased:
254       ;
255     }
256
257   return result;
258 }
259
260 int
261 target_write_memory_blocks (const std::vector<memory_write_request> &requests,
262                             enum flash_preserve_mode preserve_flash_p,
263                             void (*progress_cb) (ULONGEST, void *))
264 {
265   std::vector<memory_write_request> blocks = requests;
266   std::vector<memory_write_request> regular;
267   std::vector<memory_write_request> flash;
268   std::vector<memory_write_request> erased, garbled;
269
270   /* END == 0 would represent wraparound: a write to the very last
271      byte of the address space.  This file was not written with that
272      possibility in mind.  This is fixable, but a lot of work for a
273      rare problem; so for now, fail noisily here instead of obscurely
274      later.  */
275   for (const memory_write_request &iter : requests)
276     gdb_assert (iter.end != 0);
277
278   /* Sort the blocks by their start address.  */
279   std::sort (blocks.begin (), blocks.end (), compare_block_starting_address);
280
281   /* Split blocks into list of regular memory blocks,
282      and list of flash memory blocks.  */
283   split_regular_and_flash_blocks (blocks, &regular, &flash);
284
285   /* If a variable is added to forbid flash write, even during "load",
286      it should be checked here.  Similarly, if this function is used
287      for other situations besides "load" in which writing to flash
288      is undesirable, that should be checked here.  */
289
290   /* Find flash blocks to erase.  */
291   erased = blocks_to_erase (flash);
292
293   /* Find what flash regions will be erased, and not overwritten; then
294      either preserve or discard the old contents.  */
295   garbled = compute_garbled_blocks (erased, flash);
296
297   std::vector<gdb::unique_xmalloc_ptr<gdb_byte>> mem_holders;
298   if (!garbled.empty ())
299     {
300       if (preserve_flash_p == flash_preserve)
301         {
302           /* Read in regions that must be preserved and add them to
303              the list of blocks we read.  */
304           for (memory_write_request &iter : garbled)
305             {
306               gdb_assert (iter.data == NULL);
307               gdb::unique_xmalloc_ptr<gdb_byte> holder
308                 ((gdb_byte *) xmalloc (iter.end - iter.begin));
309               iter.data = holder.get ();
310               mem_holders.push_back (std::move (holder));
311               int err = target_read_memory (iter.begin, iter.data,
312                                             iter.end - iter.begin);
313               if (err != 0)
314                 return err;
315
316               flash.push_back (iter);
317             }
318
319           std::sort (flash.begin (), flash.end (),
320                      compare_block_starting_address);
321         }
322     }
323
324   /* We could coalesce adjacent memory blocks here, to reduce the
325      number of write requests for small sections.  However, we would
326      have to reallocate and copy the data pointers, which could be
327      large; large sections are more common in loadable objects than
328      large numbers of small sections (although the reverse can be true
329      in object files).  So, we issue at least one write request per
330      passed struct memory_write_request.  The remote stub will still
331      have the opportunity to batch flash requests.  */
332
333   /* Write regular blocks.  */
334   for (const memory_write_request &iter : regular)
335     {
336       LONGEST len;
337
338       len = target_write_with_progress (current_top_target (),
339                                         TARGET_OBJECT_MEMORY, NULL,
340                                         iter.data, iter.begin,
341                                         iter.end - iter.begin,
342                                         progress_cb, iter.baton);
343       if (len < (LONGEST) (iter.end - iter.begin))
344         {
345           /* Call error?  */
346           return -1;
347         }
348     }
349
350   if (!erased.empty ())
351     {
352       /* Erase all pages.  */
353       for (const memory_write_request &iter : erased)
354         target_flash_erase (iter.begin, iter.end - iter.begin);
355
356       /* Write flash data.  */
357       for (const memory_write_request &iter : flash)
358         {
359           LONGEST len;
360
361           len = target_write_with_progress (current_top_target (),
362                                             TARGET_OBJECT_FLASH, NULL,
363                                             iter.data, iter.begin,
364                                             iter.end - iter.begin,
365                                             progress_cb, iter.baton);
366           if (len < (LONGEST) (iter.end - iter.begin))
367             error (_("Error writing data to flash"));
368         }
369
370       target_flash_done ();
371     }
372
373   return 0;
374 }
This page took 0.047792 seconds and 4 git commands to generate.