Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / memattr.c
CommitLineData
80629b1b 1/* Memory attributes support, for GDB.
14a5e767 2
42a4f53d 3 Copyright (C) 2001-2019 Free Software Foundation, Inc.
80629b1b
EZ
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
80629b1b
EZ
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
80629b1b 19
29e57380
C
20#include "defs.h"
21#include "command.h"
22#include "gdbcmd.h"
23#include "memattr.h"
24#include "target.h"
68c765e2 25#include "target-dcache.h"
29e57380
C
26#include "value.h"
27#include "language.h"
268a13a5 28#include "gdbsupport/vec.h"
fbcb778d 29#include "breakpoint.h"
197f0a60 30#include "cli/cli-utils.h"
a664f67e 31#include <algorithm>
0d12e84c 32#include "gdbarch.h"
29e57380 33
a664f67e
SM
34static std::vector<mem_region> user_mem_region_list, target_mem_region_list;
35static std::vector<mem_region> *mem_region_list = &target_mem_region_list;
f4d650ec 36static int mem_number = 0;
29e57380 37
fd79ecee
DJ
38/* If this flag is set, the memory region list should be automatically
39 updated from the target. If it is clear, the list is user-controlled
40 and should be left alone. */
a664f67e
SM
41
42static bool
43mem_use_target ()
44{
45 return mem_region_list == &target_mem_region_list;
46}
fd79ecee
DJ
47
48/* If this flag is set, we have tried to fetch the target memory regions
49 since the last time it was invalidated. If that list is still
50 empty, then the target can't supply memory regions. */
a664f67e 51static bool target_mem_regions_valid;
fd79ecee 52
4b5752d0
VP
53/* If this flag is set, gdb will assume that memory ranges not
54 specified by the memory map have type MEM_NONE, and will
55 emit errors on all accesses to that memory. */
491144b5 56static bool inaccessible_by_default = true;
4b5752d0
VP
57
58static void
59show_inaccessible_by_default (struct ui_file *file, int from_tty,
60 struct cmd_list_element *c,
61 const char *value)
62{
63 if (inaccessible_by_default)
3e43a32a
MS
64 fprintf_filtered (file, _("Unknown memory addresses will "
65 "be treated as inaccessible.\n"));
4b5752d0 66 else
3e43a32a
MS
67 fprintf_filtered (file, _("Unknown memory addresses "
68 "will be treated as RAM.\n"));
4b5752d0
VP
69}
70
fd79ecee
DJ
71/* This function should be called before any command which would
72 modify the memory region list. It will handle switching from
73 a target-provided list to a local list, if necessary. */
74
75static void
76require_user_regions (int from_tty)
77{
fd79ecee 78 /* If we're already using a user-provided list, nothing to do. */
a664f67e 79 if (!mem_use_target ())
fd79ecee
DJ
80 return;
81
82 /* Switch to a user-provided list (possibly a copy of the current
83 one). */
a664f67e 84 mem_region_list = &user_mem_region_list;
fd79ecee
DJ
85
86 /* If we don't have a target-provided region list yet, then
87 no need to warn. */
a664f67e 88 if (target_mem_region_list.empty ())
fd79ecee
DJ
89 return;
90
91 /* Otherwise, let the user know how to get back. */
92 if (from_tty)
93 warning (_("Switching to manual control of memory regions; use "
94 "\"mem auto\" to fetch regions from the target again."));
95
a664f67e
SM
96 /* And create a new list (copy of the target-supplied regions) for the user
97 to modify. */
98 user_mem_region_list = target_mem_region_list;
fd79ecee
DJ
99}
100
101/* This function should be called before any command which would
102 read the memory region list, other than those which call
103 require_user_regions. It will handle fetching the
104 target-provided list, if necessary. */
105
106static void
107require_target_regions (void)
108{
a664f67e 109 if (mem_use_target () && !target_mem_regions_valid)
fd79ecee 110 {
a664f67e 111 target_mem_regions_valid = true;
fd79ecee 112 target_mem_region_list = target_memory_map ();
fd79ecee
DJ
113 }
114}
115
a664f67e
SM
116/* Create a new user-defined memory region. */
117
c96fc75e 118static void
a664f67e
SM
119create_user_mem_region (CORE_ADDR lo, CORE_ADDR hi,
120 const mem_attrib &attrib)
29e57380 121{
025bb325 122 /* lo == hi is a useless empty region. */
2b236d82 123 if (lo >= hi && hi != 0)
29e57380 124 {
a3f17187 125 printf_unfiltered (_("invalid memory region: low >= high\n"));
c96fc75e 126 return;
29e57380
C
127 }
128
a664f67e 129 mem_region newobj (lo, hi, attrib);
c96fc75e 130
a664f67e
SM
131 auto it = std::lower_bound (user_mem_region_list.begin (),
132 user_mem_region_list.end (),
133 newobj);
134 int ix = std::distance (user_mem_region_list.begin (), it);
c96fc75e
DJ
135
136 /* Check for an overlapping memory region. We only need to check
137 in the vicinity - at most one before and one after the
138 insertion point. */
a664f67e 139 for (int i = ix - 1; i < ix + 1; i++)
29e57380 140 {
c96fc75e
DJ
141 if (i < 0)
142 continue;
a664f67e 143 if (i >= user_mem_region_list.size ())
c96fc75e
DJ
144 continue;
145
a664f67e 146 mem_region &n = user_mem_region_list[i];
c96fc75e 147
a664f67e
SM
148 if ((lo >= n.lo && (lo < n.hi || n.hi == 0))
149 || (hi > n.lo && (hi <= n.hi || n.hi == 0))
150 || (lo <= n.lo && ((hi >= n.hi && n.hi != 0) || hi == 0)))
29e57380 151 {
a3f17187 152 printf_unfiltered (_("overlapping memory region\n"));
c96fc75e 153 return;
29e57380
C
154 }
155 }
156
fe978cb0 157 newobj.number = ++mem_number;
a664f67e 158 user_mem_region_list.insert (it, newobj);
29e57380
C
159}
160
a664f67e
SM
161/* Look up the memory region corresponding to ADDR. */
162
29e57380
C
163struct mem_region *
164lookup_mem_region (CORE_ADDR addr)
165{
a664f67e 166 static struct mem_region region (0, 0);
29e57380
C
167 CORE_ADDR lo;
168 CORE_ADDR hi;
169
fd79ecee
DJ
170 require_target_regions ();
171
29e57380
C
172 /* First we initialize LO and HI so that they describe the entire
173 memory space. As we process the memory region chain, they are
174 redefined to describe the minimal region containing ADDR. LO
175 and HI are used in the case where no memory region is defined
176 that contains ADDR. If a memory region is disabled, it is
a76d924d
DJ
177 treated as if it does not exist. The initial values for LO
178 and HI represent the bottom and top of memory. */
29e57380 179
a76d924d
DJ
180 lo = 0;
181 hi = 0;
29e57380 182
a664f67e 183 /* Either find memory range containing ADDR, or set LO and HI
4b5752d0
VP
184 to the nearest boundaries of an existing memory range.
185
186 If we ever want to support a huge list of memory regions, this
c96fc75e
DJ
187 check should be replaced with a binary search (probably using
188 VEC_lower_bound). */
a664f67e 189 for (mem_region &m : *mem_region_list)
29e57380 190 {
a664f67e 191 if (m.enabled_p == 1)
29e57380 192 {
3e43a32a
MS
193 /* If the address is in the memory region, return that
194 memory range. */
a664f67e
SM
195 if (addr >= m.lo && (addr < m.hi || m.hi == 0))
196 return &m;
29e57380 197
a76d924d
DJ
198 /* This (correctly) won't match if m->hi == 0, representing
199 the top of the address space, because CORE_ADDR is unsigned;
200 no value of LO is less than zero. */
a664f67e
SM
201 if (addr >= m.hi && lo < m.hi)
202 lo = m.hi;
29e57380 203
a76d924d
DJ
204 /* This will never set HI to zero; if we're here and ADDR
205 is at or below M, and the region starts at zero, then ADDR
206 would have been in the region. */
a664f67e
SM
207 if (addr <= m.lo && (hi == 0 || hi > m.lo))
208 hi = m.lo;
29e57380
C
209 }
210 }
211
212 /* Because no region was found, we must cons up one based on what
213 was learned above. */
214 region.lo = lo;
215 region.hi = hi;
4b5752d0
VP
216
217 /* When no memory map is defined at all, we always return
218 'default_mem_attrib', so that we do not make all memory
219 inaccessible for targets that don't provide a memory map. */
a664f67e
SM
220 if (inaccessible_by_default && !mem_region_list->empty ())
221 region.attrib = mem_attrib::unknown ();
4b5752d0 222 else
a664f67e 223 region.attrib = mem_attrib ();
4b5752d0 224
29e57380
C
225 return &region;
226}
fd79ecee
DJ
227
228/* Invalidate any memory regions fetched from the target. */
229
230void
231invalidate_target_mem_regions (void)
232{
fd79ecee
DJ
233 if (!target_mem_regions_valid)
234 return;
235
a664f67e
SM
236 target_mem_regions_valid = false;
237 target_mem_region_list.clear ();
fd79ecee
DJ
238}
239
a664f67e 240/* Clear user-defined memory region list. */
fd79ecee
DJ
241
242static void
a664f67e 243user_mem_clear (void)
fd79ecee 244{
a664f67e 245 user_mem_region_list.clear ();
fd79ecee 246}
29e57380
C
247\f
248
249static void
0b39b52e 250mem_command (const char *args, int from_tty)
29e57380
C
251{
252 CORE_ADDR lo, hi;
29e57380
C
253
254 if (!args)
e2e0b3e5 255 error_no_arg (_("No mem"));
29e57380 256
fd79ecee
DJ
257 /* For "mem auto", switch back to using a target provided list. */
258 if (strcmp (args, "auto") == 0)
259 {
a664f67e 260 if (mem_use_target ())
fd79ecee
DJ
261 return;
262
a664f67e
SM
263 user_mem_clear ();
264 mem_region_list = &target_mem_region_list;
fd79ecee 265
fd79ecee
DJ
266 return;
267 }
268
269 require_user_regions (from_tty);
270
0b39b52e
TT
271 std::string tok = extract_arg (&args);
272 if (tok == "")
8a3fe4f8 273 error (_("no lo address"));
0b39b52e 274 lo = parse_and_eval_address (tok.c_str ());
29e57380 275
0b39b52e
TT
276 tok = extract_arg (&args);
277 if (tok == "")
8a3fe4f8 278 error (_("no hi address"));
0b39b52e 279 hi = parse_and_eval_address (tok.c_str ());
29e57380 280
a664f67e 281 mem_attrib attrib;
0b39b52e 282 while ((tok = extract_arg (&args)) != "")
29e57380 283 {
0b39b52e 284 if (tok == "rw")
29e57380 285 attrib.mode = MEM_RW;
0b39b52e 286 else if (tok == "ro")
29e57380 287 attrib.mode = MEM_RO;
0b39b52e 288 else if (tok == "wo")
29e57380
C
289 attrib.mode = MEM_WO;
290
0b39b52e 291 else if (tok == "8")
29e57380 292 attrib.width = MEM_WIDTH_8;
0b39b52e 293 else if (tok == "16")
29e57380
C
294 {
295 if ((lo % 2 != 0) || (hi % 2 != 0))
8a3fe4f8 296 error (_("region bounds not 16 bit aligned"));
29e57380
C
297 attrib.width = MEM_WIDTH_16;
298 }
0b39b52e 299 else if (tok == "32")
29e57380
C
300 {
301 if ((lo % 4 != 0) || (hi % 4 != 0))
8a3fe4f8 302 error (_("region bounds not 32 bit aligned"));
29e57380
C
303 attrib.width = MEM_WIDTH_32;
304 }
0b39b52e 305 else if (tok == "64")
29e57380
C
306 {
307 if ((lo % 8 != 0) || (hi % 8 != 0))
8a3fe4f8 308 error (_("region bounds not 64 bit aligned"));
29e57380
C
309 attrib.width = MEM_WIDTH_64;
310 }
311
312#if 0
0b39b52e 313 else if (tok == "hwbreak")
81a9a963 314 attrib.hwbreak = 1;
0b39b52e 315 else if (tok == "swbreak")
81a9a963 316 attrib.hwbreak = 0;
29e57380
C
317#endif
318
0b39b52e 319 else if (tok == "cache")
81a9a963 320 attrib.cache = 1;
0b39b52e 321 else if (tok == "nocache")
81a9a963 322 attrib.cache = 0;
29e57380
C
323
324#if 0
0b39b52e 325 else if (tok == "verify")
81a9a963 326 attrib.verify = 1;
0b39b52e 327 else if (tok == "noverify")
81a9a963 328 attrib.verify = 0;
29e57380
C
329#endif
330
331 else
0b39b52e 332 error (_("unknown attribute: %s"), tok.c_str ());
29e57380
C
333 }
334
a664f67e 335 create_user_mem_region (lo, hi, attrib);
29e57380
C
336}
337\f
338
339static void
1d12d88f 340info_mem_command (const char *args, int from_tty)
29e57380 341{
a664f67e 342 if (mem_use_target ())
fd79ecee
DJ
343 printf_filtered (_("Using memory regions provided by the target.\n"));
344 else
345 printf_filtered (_("Using user-defined memory regions.\n"));
346
347 require_target_regions ();
348
a664f67e 349 if (mem_region_list->empty ())
29e57380 350 {
a3f17187 351 printf_unfiltered (_("There are no memory regions defined.\n"));
29e57380
C
352 return;
353 }
354
ab35b611
EZ
355 printf_filtered ("Num ");
356 printf_filtered ("Enb ");
357 printf_filtered ("Low Addr ");
f5656ead 358 if (gdbarch_addr_bit (target_gdbarch ()) > 32)
ab35b611
EZ
359 printf_filtered (" ");
360 printf_filtered ("High Addr ");
f5656ead 361 if (gdbarch_addr_bit (target_gdbarch ()) > 32)
ab35b611
EZ
362 printf_filtered (" ");
363 printf_filtered ("Attrs ");
364 printf_filtered ("\n");
365
a664f67e 366 for (const mem_region &m : *mem_region_list)
29e57380 367 {
a121b7c1 368 const char *tmp;
b8d56208 369
ab35b611 370 printf_filtered ("%-3d %-3c\t",
a664f67e
SM
371 m.number,
372 m.enabled_p ? 'y' : 'n');
f5656ead 373 if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
a664f67e 374 tmp = hex_string_custom (m.lo, 8);
ab35b611 375 else
a664f67e 376 tmp = hex_string_custom (m.lo, 16);
ab35b611
EZ
377
378 printf_filtered ("%s ", tmp);
2b236d82 379
f5656ead 380 if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
2163ab9d 381 {
a664f67e 382 if (m.hi == 0)
b8d56208
MS
383 tmp = "0x100000000";
384 else
a664f67e 385 tmp = hex_string_custom (m.hi, 8);
2163ab9d 386 }
ab35b611 387 else
2163ab9d 388 {
a664f67e 389 if (m.hi == 0)
b8d56208
MS
390 tmp = "0x10000000000000000";
391 else
a664f67e 392 tmp = hex_string_custom (m.hi, 16);
2163ab9d
DH
393 }
394
ab35b611 395 printf_filtered ("%s ", tmp);
29e57380
C
396
397 /* Print a token for each attribute.
398
399 * FIXME: Should we output a comma after each token? It may
400 * make it easier for users to read, but we'd lose the ability
401 * to cut-and-paste the list of attributes when defining a new
402 * region. Perhaps that is not important.
403 *
404 * FIXME: If more attributes are added to GDB, the output may
405 * become cluttered and difficult for users to read. At that
406 * time, we may want to consider printing tokens only if they
407 * are different from the default attribute. */
408
a664f67e 409 switch (m.attrib.mode)
29e57380
C
410 {
411 case MEM_RW:
412 printf_filtered ("rw ");
413 break;
414 case MEM_RO:
415 printf_filtered ("ro ");
416 break;
417 case MEM_WO:
418 printf_filtered ("wo ");
419 break;
fd79ecee 420 case MEM_FLASH:
a664f67e 421 printf_filtered ("flash blocksize 0x%x ", m.attrib.blocksize);
fd79ecee 422 break;
29e57380
C
423 }
424
a664f67e 425 switch (m.attrib.width)
29e57380
C
426 {
427 case MEM_WIDTH_8:
428 printf_filtered ("8 ");
429 break;
430 case MEM_WIDTH_16:
431 printf_filtered ("16 ");
432 break;
433 case MEM_WIDTH_32:
434 printf_filtered ("32 ");
435 break;
436 case MEM_WIDTH_64:
437 printf_filtered ("64 ");
438 break;
439 case MEM_WIDTH_UNSPECIFIED:
440 break;
441 }
442
443#if 0
444 if (attrib->hwbreak)
445 printf_filtered ("hwbreak");
446 else
447 printf_filtered ("swbreak");
448#endif
449
a664f67e 450 if (m.attrib.cache)
29e57380
C
451 printf_filtered ("cache ");
452 else
453 printf_filtered ("nocache ");
454
455#if 0
456 if (attrib->verify)
457 printf_filtered ("verify ");
458 else
459 printf_filtered ("noverify ");
460#endif
461
462 printf_filtered ("\n");
29e57380
C
463 }
464}
465\f
466
025bb325 467/* Enable the memory region number NUM. */
29e57380
C
468
469static void
470mem_enable (int num)
471{
a664f67e
SM
472 for (mem_region &m : *mem_region_list)
473 if (m.number == num)
29e57380 474 {
a664f67e 475 m.enabled_p = 1;
29e57380
C
476 return;
477 }
a3f17187 478 printf_unfiltered (_("No memory region number %d.\n"), num);
29e57380
C
479}
480
481static void
4465d9db 482enable_mem_command (const char *args, int from_tty)
29e57380 483{
fd79ecee
DJ
484 require_user_regions (from_tty);
485
4e5d721f 486 target_dcache_invalidate ();
29e57380 487
fbcb778d
MS
488 if (args == NULL || *args == '\0')
489 { /* Enable all mem regions. */
a664f67e
SM
490 for (mem_region &m : *mem_region_list)
491 m.enabled_p = 1;
29e57380
C
492 }
493 else
197f0a60 494 {
bfd28288
PA
495 number_or_range_parser parser (args);
496 while (!parser.finished ())
197f0a60 497 {
a664f67e 498 int num = parser.get_number ();
197f0a60
TT
499 mem_enable (num);
500 }
501 }
29e57380
C
502}
503\f
504
025bb325 505/* Disable the memory region number NUM. */
29e57380
C
506
507static void
508mem_disable (int num)
509{
a664f67e
SM
510 for (mem_region &m : *mem_region_list)
511 if (m.number == num)
29e57380 512 {
a664f67e 513 m.enabled_p = 0;
29e57380
C
514 return;
515 }
a3f17187 516 printf_unfiltered (_("No memory region number %d.\n"), num);
29e57380
C
517}
518
519static void
4465d9db 520disable_mem_command (const char *args, int from_tty)
29e57380 521{
fd79ecee
DJ
522 require_user_regions (from_tty);
523
4e5d721f 524 target_dcache_invalidate ();
29e57380 525
fbcb778d 526 if (args == NULL || *args == '\0')
29e57380 527 {
a664f67e
SM
528 for (mem_region &m : *mem_region_list)
529 m.enabled_p = false;
29e57380
C
530 }
531 else
197f0a60 532 {
bfd28288
PA
533 number_or_range_parser parser (args);
534 while (!parser.finished ())
197f0a60 535 {
bfd28288 536 int num = parser.get_number ();
197f0a60
TT
537 mem_disable (num);
538 }
539 }
29e57380
C
540}
541
025bb325 542/* Delete the memory region number NUM. */
29e57380
C
543
544static void
545mem_delete (int num)
546{
c96fc75e 547 if (!mem_region_list)
29e57380 548 {
a3f17187 549 printf_unfiltered (_("No memory region number %d.\n"), num);
29e57380
C
550 return;
551 }
552
a664f67e
SM
553 auto it = std::remove_if (mem_region_list->begin (), mem_region_list->end (),
554 [num] (const mem_region &m)
29e57380 555 {
a664f67e
SM
556 return m.number == num;
557 });
c96fc75e 558
a664f67e
SM
559 if (it != mem_region_list->end ())
560 mem_region_list->erase (it);
561 else
562 printf_unfiltered (_("No memory region number %d.\n"), num);
29e57380
C
563}
564
565static void
4465d9db 566delete_mem_command (const char *args, int from_tty)
29e57380 567{
fd79ecee
DJ
568 require_user_regions (from_tty);
569
4e5d721f 570 target_dcache_invalidate ();
29e57380 571
fbcb778d 572 if (args == NULL || *args == '\0')
29e57380 573 {
9e2f0ad4 574 if (query (_("Delete all memory regions? ")))
a664f67e 575 user_mem_clear ();
29e57380
C
576 dont_repeat ();
577 return;
578 }
579
bfd28288
PA
580 number_or_range_parser parser (args);
581 while (!parser.finished ())
29e57380 582 {
bfd28288 583 int num = parser.get_number ();
29e57380 584 mem_delete (num);
29e57380
C
585 }
586
587 dont_repeat ();
588}
4b5752d0
VP
589
590static void
981a3fb3 591dummy_cmd (const char *args, int from_tty)
4b5752d0
VP
592{
593}
b9362cc7 594
4b5752d0
VP
595static struct cmd_list_element *mem_set_cmdlist;
596static struct cmd_list_element *mem_show_cmdlist;
597
29e57380 598void
5ae5f592 599_initialize_mem (void)
29e57380 600{
1bedd215 601 add_com ("mem", class_vars, mem_command, _("\
590042fc
PW
602Define attributes for memory region or reset memory region handling to "
603"target-based.\n\
fd79ecee 604Usage: mem auto\n\
99806209
TT
605 mem LOW HIGH [MODE WIDTH CACHE],\n\
606where MODE may be rw (read/write), ro (read-only) or wo (write-only),\n\
607 WIDTH may be 8, 16, 32, or 64, and\n\
608 CACHE may be cache or nocache"));
29e57380 609
ae3b3f34 610 add_cmd ("mem", class_vars, enable_mem_command, _("\
1a966eab 611Enable memory region.\n\
99806209
TT
612Arguments are the IDs of the memory regions to enable.\n\
613Usage: enable mem [ID]...\n\
614Do \"info mem\" to see current list of IDs."), &enablelist);
29e57380 615
ae3b3f34 616 add_cmd ("mem", class_vars, disable_mem_command, _("\
1a966eab 617Disable memory region.\n\
99806209
TT
618Arguments are the IDs of the memory regions to disable.\n\
619Usage: disable mem [ID]...\n\
620Do \"info mem\" to see current list of IDs."), &disablelist);
29e57380 621
ae3b3f34 622 add_cmd ("mem", class_vars, delete_mem_command, _("\
1a966eab 623Delete memory region.\n\
99806209
TT
624Arguments are the IDs of the memory regions to delete.\n\
625Usage: delete mem [ID]...\n\
626Do \"info mem\" to see current list of IDs."), &deletelist);
29e57380 627
ae3b3f34 628 add_info ("mem", info_mem_command,
590042fc 629 _("Memory region attributes."));
4b5752d0
VP
630
631 add_prefix_cmd ("mem", class_vars, dummy_cmd, _("\
590042fc 632Memory regions settings."),
4b5752d0
VP
633 &mem_set_cmdlist, "set mem ",
634 0/* allow-unknown */, &setlist);
635 add_prefix_cmd ("mem", class_vars, dummy_cmd, _("\
590042fc 636Memory regions settings."),
4b5752d0
VP
637 &mem_show_cmdlist, "show mem ",
638 0/* allow-unknown */, &showlist);
639
640 add_setshow_boolean_cmd ("inaccessible-by-default", no_class,
641 &inaccessible_by_default, _("\
642Set handling of unknown memory regions."), _("\
643Show handling of unknown memory regions."), _("\
644If on, and some memory map is defined, debugger will emit errors on\n\
645accesses to memory not defined in the memory map. If off, accesses to all\n\
646memory addresses will be allowed."),
647 NULL,
648 show_inaccessible_by_default,
649 &mem_set_cmdlist,
650 &mem_show_cmdlist);
29e57380 651}
This page took 1.71936 seconds and 4 git commands to generate.