GDB (API)
/home/stan/gdb/src/gdb/target-memory.c
Go to the documentation of this file.
00001 /* Parts of target interface that deal with accessing memory and memory-like
00002    objects.
00003 
00004    Copyright (C) 2006-2013 Free Software Foundation, Inc.
00005 
00006    This file is part of GDB.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 3 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00020 
00021 #include "defs.h"
00022 #include "vec.h"
00023 #include "target.h"
00024 #include "memory-map.h"
00025 
00026 #include "gdb_assert.h"
00027 
00028 #include <stdio.h>
00029 #include <sys/time.h>
00030 
00031 static int
00032 compare_block_starting_address (const void *a, const void *b)
00033 {
00034   const struct memory_write_request *a_req = a;
00035   const struct memory_write_request *b_req = b;
00036 
00037   if (a_req->begin < b_req->begin)
00038     return -1;
00039   else if (a_req->begin == b_req->begin)
00040     return 0;
00041   else
00042     return 1;
00043 }
00044 
00045 /* Adds to RESULT all memory write requests from BLOCK that are
00046    in [BEGIN, END) range.
00047 
00048    If any memory request is only partially in the specified range,
00049    that part of the memory request will be added.  */
00050 
00051 static void
00052 claim_memory (VEC(memory_write_request_s) *blocks,
00053               VEC(memory_write_request_s) **result,
00054               ULONGEST begin,
00055               ULONGEST end)
00056 {
00057   int i;
00058   ULONGEST claimed_begin;
00059   ULONGEST claimed_end;
00060   struct memory_write_request *r;
00061 
00062   for (i = 0; VEC_iterate (memory_write_request_s, blocks, i, r); ++i)
00063     {
00064       /* If the request doesn't overlap [BEGIN, END), skip it.  We
00065          must handle END == 0 meaning the top of memory; we don't yet
00066          check for R->end == 0, which would also mean the top of
00067          memory, but there's an assertion in
00068          target_write_memory_blocks which checks for that.  */
00069 
00070       if (begin >= r->end)
00071         continue;
00072       if (end != 0 && end <= r->begin)
00073         continue;
00074 
00075       claimed_begin = max (begin, r->begin);
00076       if (end == 0)
00077         claimed_end = r->end;
00078       else
00079         claimed_end = min (end, r->end);
00080 
00081       if (claimed_begin == r->begin && claimed_end == r->end)
00082         VEC_safe_push (memory_write_request_s, *result, r);
00083       else
00084         {
00085           struct memory_write_request *n =
00086             VEC_safe_push (memory_write_request_s, *result, NULL);
00087 
00088           *n = *r;
00089           n->begin = claimed_begin;
00090           n->end = claimed_end;
00091           n->data += claimed_begin - r->begin;
00092         }
00093     }
00094 }
00095 
00096 /* Given a vector of struct memory_write_request objects in BLOCKS,
00097    add memory requests for flash memory into FLASH_BLOCKS, and for
00098    regular memory to REGULAR_BLOCKS.  */
00099 
00100 static void
00101 split_regular_and_flash_blocks (VEC(memory_write_request_s) *blocks,
00102                                 VEC(memory_write_request_s) **regular_blocks,
00103                                 VEC(memory_write_request_s) **flash_blocks)
00104 {
00105   struct mem_region *region;
00106   CORE_ADDR cur_address;
00107 
00108   /* This implementation runs in O(length(regions)*length(blocks)) time.
00109      However, in most cases the number of blocks will be small, so this does
00110      not matter.
00111 
00112      Note also that it's extremely unlikely that a memory write request
00113      will span more than one memory region, however for safety we handle
00114      such situations.  */
00115 
00116   cur_address = 0;
00117   while (1)
00118     {
00119       VEC(memory_write_request_s) **r;
00120 
00121       region = lookup_mem_region (cur_address);
00122       r = region->attrib.mode == MEM_FLASH ? flash_blocks : regular_blocks;
00123       cur_address = region->hi;
00124       claim_memory (blocks, r, region->lo, region->hi);
00125 
00126       if (cur_address == 0)
00127         break;
00128     }
00129 }
00130 
00131 /* Given an ADDRESS, if BEGIN is non-NULL this function sets *BEGIN
00132    to the start of the flash block containing the address.  Similarly,
00133    if END is non-NULL *END will be set to the address one past the end
00134    of the block containing the address.  */
00135 
00136 static void
00137 block_boundaries (CORE_ADDR address, CORE_ADDR *begin, CORE_ADDR *end)
00138 {
00139   struct mem_region *region;
00140   unsigned blocksize;
00141 
00142   region = lookup_mem_region (address);
00143   gdb_assert (region->attrib.mode == MEM_FLASH);
00144   blocksize = region->attrib.blocksize;
00145   if (begin)
00146     *begin = address / blocksize * blocksize;
00147   if (end)
00148     *end = (address + blocksize - 1) / blocksize * blocksize;
00149 }
00150 
00151 /* Given the list of memory requests to be WRITTEN, this function
00152    returns write requests covering each group of flash blocks which must
00153    be erased.  */
00154 
00155 static VEC(memory_write_request_s) *
00156 blocks_to_erase (VEC(memory_write_request_s) *written)
00157 {
00158   unsigned i;
00159   struct memory_write_request *ptr;
00160 
00161   VEC(memory_write_request_s) *result = NULL;
00162 
00163   for (i = 0; VEC_iterate (memory_write_request_s, written, i, ptr); ++i)
00164     {
00165       CORE_ADDR begin, end;
00166 
00167       block_boundaries (ptr->begin, &begin, 0);
00168       block_boundaries (ptr->end - 1, 0, &end);
00169 
00170       if (!VEC_empty (memory_write_request_s, result)
00171           && VEC_last (memory_write_request_s, result)->end >= begin)
00172         {
00173           VEC_last (memory_write_request_s, result)->end = end;
00174         }
00175       else
00176         {
00177           struct memory_write_request *n =
00178             VEC_safe_push (memory_write_request_s, result, NULL);
00179 
00180           memset (n, 0, sizeof (struct memory_write_request));
00181           n->begin = begin;
00182           n->end = end;
00183         }
00184     }
00185 
00186   return result;
00187 }
00188 
00189 /* Given ERASED_BLOCKS, a list of blocks that will be erased with
00190    flash erase commands, and WRITTEN_BLOCKS, the list of memory
00191    addresses that will be written, compute the set of memory addresses
00192    that will be erased but not rewritten (e.g. padding within a block
00193    which is only partially filled by "load").  */
00194 
00195 static VEC(memory_write_request_s) *
00196 compute_garbled_blocks (VEC(memory_write_request_s) *erased_blocks,
00197                         VEC(memory_write_request_s) *written_blocks)
00198 {
00199   VEC(memory_write_request_s) *result = NULL;
00200 
00201   unsigned i, j;
00202   unsigned je = VEC_length (memory_write_request_s, written_blocks);
00203   struct memory_write_request *erased_p;
00204 
00205   /* Look at each erased memory_write_request in turn, and
00206      see what part of it is subsequently written to.
00207 
00208      This implementation is O(length(erased) * length(written)).  If
00209      the lists are sorted at this point it could be rewritten more
00210      efficiently, but the complexity is not generally worthwhile.  */
00211 
00212   for (i = 0;
00213        VEC_iterate (memory_write_request_s, erased_blocks, i, erased_p);
00214        ++i)
00215     {
00216       /* Make a deep copy -- it will be modified inside the loop, but
00217          we don't want to modify original vector.  */
00218       struct memory_write_request erased = *erased_p;
00219 
00220       for (j = 0; j != je;)
00221         {
00222           struct memory_write_request *written
00223             = VEC_index (memory_write_request_s,
00224                          written_blocks, j);
00225 
00226           /* Now try various cases.  */
00227 
00228           /* If WRITTEN is fully to the left of ERASED, check the next
00229              written memory_write_request.  */
00230           if (written->end <= erased.begin)
00231             {
00232               ++j;
00233               continue;
00234             }
00235 
00236           /* If WRITTEN is fully to the right of ERASED, then ERASED
00237              is not written at all.  WRITTEN might affect other
00238              blocks.  */
00239           if (written->begin >= erased.end)
00240             {
00241               VEC_safe_push (memory_write_request_s, result, &erased);
00242               goto next_erased;
00243             }
00244 
00245           /* If all of ERASED is completely written, we can move on to
00246              the next erased region.  */
00247           if (written->begin <= erased.begin
00248               && written->end >= erased.end)
00249             {
00250               goto next_erased;
00251             }
00252 
00253           /* If there is an unwritten part at the beginning of ERASED,
00254              then we should record that part and try this inner loop
00255              again for the remainder.  */
00256           if (written->begin > erased.begin)
00257             {
00258               struct memory_write_request *n =
00259                 VEC_safe_push (memory_write_request_s, result, NULL);
00260 
00261               memset (n, 0, sizeof (struct memory_write_request));
00262               n->begin = erased.begin;
00263               n->end = written->begin;
00264               erased.begin = written->begin;
00265               continue;
00266             }
00267 
00268           /* If there is an unwritten part at the end of ERASED, we
00269              forget about the part that was written to and wait to see
00270              if the next write request writes more of ERASED.  We can't
00271              push it yet.  */
00272           if (written->end < erased.end)
00273             {
00274               erased.begin = written->end;
00275               ++j;
00276               continue;
00277             }
00278         }
00279 
00280       /* If we ran out of write requests without doing anything about
00281          ERASED, then that means it's really erased.  */
00282       VEC_safe_push (memory_write_request_s, result, &erased);
00283 
00284     next_erased:
00285       ;
00286     }
00287 
00288   return result;
00289 }
00290 
00291 static void
00292 cleanup_request_data (void *p)
00293 {
00294   VEC(memory_write_request_s) **v = p;
00295   struct memory_write_request *r;
00296   int i;
00297 
00298   for (i = 0; VEC_iterate (memory_write_request_s, *v, i, r); ++i)
00299     xfree (r->data);
00300 }
00301 
00302 static void
00303 cleanup_write_requests_vector (void *p)
00304 {
00305   VEC(memory_write_request_s) **v = p;
00306 
00307   VEC_free (memory_write_request_s, *v);
00308 }
00309 
00310 int
00311 target_write_memory_blocks (VEC(memory_write_request_s) *requests,
00312                             enum flash_preserve_mode preserve_flash_p,
00313                             void (*progress_cb) (ULONGEST, void *))
00314 {
00315   struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
00316   VEC(memory_write_request_s) *blocks = VEC_copy (memory_write_request_s,
00317                                                   requests);
00318   unsigned i;
00319   int err = 0;
00320   struct memory_write_request *r;
00321   VEC(memory_write_request_s) *regular = NULL;
00322   VEC(memory_write_request_s) *flash = NULL;
00323   VEC(memory_write_request_s) *erased, *garbled;
00324 
00325   /* END == 0 would represent wraparound: a write to the very last
00326      byte of the address space.  This file was not written with that
00327      possibility in mind.  This is fixable, but a lot of work for a
00328      rare problem; so for now, fail noisily here instead of obscurely
00329      later.  */
00330   for (i = 0; VEC_iterate (memory_write_request_s, requests, i, r); ++i)
00331     gdb_assert (r->end != 0);
00332 
00333   make_cleanup (cleanup_write_requests_vector, &blocks);
00334 
00335   /* Sort the blocks by their start address.  */
00336   qsort (VEC_address (memory_write_request_s, blocks),
00337          VEC_length (memory_write_request_s, blocks),
00338          sizeof (struct memory_write_request), compare_block_starting_address);
00339 
00340   /* Split blocks into list of regular memory blocks,
00341      and list of flash memory blocks.  */
00342   make_cleanup (cleanup_write_requests_vector, &regular);
00343   make_cleanup (cleanup_write_requests_vector, &flash);
00344   split_regular_and_flash_blocks (blocks, &regular, &flash);
00345 
00346   /* If a variable is added to forbid flash write, even during "load",
00347      it should be checked here.  Similarly, if this function is used
00348      for other situations besides "load" in which writing to flash
00349      is undesirable, that should be checked here.  */
00350 
00351   /* Find flash blocks to erase.  */
00352   erased = blocks_to_erase (flash);
00353   make_cleanup (cleanup_write_requests_vector, &erased);
00354 
00355   /* Find what flash regions will be erased, and not overwritten; then
00356      either preserve or discard the old contents.  */
00357   garbled = compute_garbled_blocks (erased, flash);
00358   make_cleanup (cleanup_request_data, &garbled);
00359   make_cleanup (cleanup_write_requests_vector, &garbled);
00360 
00361   if (!VEC_empty (memory_write_request_s, garbled))
00362     {
00363       if (preserve_flash_p == flash_preserve)
00364         {
00365           struct memory_write_request *r;
00366 
00367           /* Read in regions that must be preserved and add them to
00368              the list of blocks we read.  */
00369           for (i = 0; VEC_iterate (memory_write_request_s, garbled, i, r); ++i)
00370             {
00371               gdb_assert (r->data == NULL);
00372               r->data = xmalloc (r->end - r->begin);
00373               err = target_read_memory (r->begin, r->data, r->end - r->begin);
00374               if (err != 0)
00375                 goto out;
00376 
00377               VEC_safe_push (memory_write_request_s, flash, r);
00378             }
00379 
00380           qsort (VEC_address (memory_write_request_s, flash),
00381                  VEC_length (memory_write_request_s, flash),
00382                  sizeof (struct memory_write_request),
00383                  compare_block_starting_address);
00384         }
00385     }
00386 
00387   /* We could coalesce adjacent memory blocks here, to reduce the
00388      number of write requests for small sections.  However, we would
00389      have to reallocate and copy the data pointers, which could be
00390      large; large sections are more common in loadable objects than
00391      large numbers of small sections (although the reverse can be true
00392      in object files).  So, we issue at least one write request per
00393      passed struct memory_write_request.  The remote stub will still
00394      have the opportunity to batch flash requests.  */
00395 
00396   /* Write regular blocks.  */
00397   for (i = 0; VEC_iterate (memory_write_request_s, regular, i, r); ++i)
00398     {
00399       LONGEST len;
00400 
00401       len = target_write_with_progress (current_target.beneath,
00402                                         TARGET_OBJECT_MEMORY, NULL,
00403                                         r->data, r->begin, r->end - r->begin,
00404                                         progress_cb, r->baton);
00405       if (len < (LONGEST) (r->end - r->begin))
00406         {
00407           /* Call error?  */
00408           err = -1;
00409           goto out;
00410         }
00411     }
00412 
00413   if (!VEC_empty (memory_write_request_s, erased))
00414     {
00415       /* Erase all pages.  */
00416       for (i = 0; VEC_iterate (memory_write_request_s, erased, i, r); ++i)
00417         target_flash_erase (r->begin, r->end - r->begin);
00418 
00419       /* Write flash data.  */
00420       for (i = 0; VEC_iterate (memory_write_request_s, flash, i, r); ++i)
00421         {
00422           LONGEST len;
00423 
00424           len = target_write_with_progress (&current_target,
00425                                             TARGET_OBJECT_FLASH, NULL,
00426                                             r->data, r->begin,
00427                                             r->end - r->begin,
00428                                             progress_cb, r->baton);
00429           if (len < (LONGEST) (r->end - r->begin))
00430             error (_("Error writing data to flash"));
00431         }
00432 
00433       target_flash_done ();
00434     }
00435 
00436  out:
00437   do_cleanups (back_to);
00438 
00439   return err;
00440 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines