GDB (API)
|
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, ®ular); 00343 make_cleanup (cleanup_write_requests_vector, &flash); 00344 split_regular_and_flash_blocks (blocks, ®ular, &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 (¤t_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 }