qemuのゲストメモリをホストのデバッガから確認する

# 目的
Exception発生時などにメモリダンプとかしたい

# cortex-m

## マシンコード内

sは`ARMv7MState`を持つマシン作成時の構造体。(例えば`STM32F100State`みたいな)
nは`memory_region_add_subregion`の順と思われる。

```
((CPUState*)s->armv7m ->cpu)->cpu_ases [0].memory_dispatch ->map .sections[n].mr->ram_block->host 
```

ファイルに吐き出すならこんな感じ
```c
uint8_t *p = ((CPUState*)s->armv7m->cpu)->cpu_ases [0].memory_dispatch ->map .sections[n].mr->ram_block->host;

FILE *fp;
if ((fp = fopen(DUMP_FILE_NAME, "wb")) != 0) {
  fwrite(p, RAM_SIZE, 1, fp);
  fclose(fp);
}
```
## アボート時

callback登録しておくと便利な気がする。
標準で無いのかな？

```diff
tyano:qemu$ git diff system/ hw/intc/ | cat
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 404a445138..00d3776643 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -28,6 +28,7 @@
 #include "qemu/module.h"
 #include "trace.h"
 
+void (*machine_specific_memory_dump)(MemoryRegion*);
 /* IRQ number counting:
  *
  * the num-irq property counts the number of external IRQ lines
@@ -521,6 +522,7 @@ static void armv7m_nvic_clear_pending(NVICState *s, int irq, bool secure)
     }
 }
 
+MemoryRegionSection *get_memory_region_section(ARMCPU *cpu);
 static void do_armv7m_nvic_set_pending(void *opaque, int irq, bool secure,
                                        bool derived)
 {
@@ -645,6 +647,17 @@ static void do_armv7m_nvic_set_pending(void *opaque, int irq, bool secure,
                  * Lockup condition due to a guest bug. We don't model
                  * Lockup, so report via cpu_abort() instead.
                  */
+
+if (machine_specific_memory_dump) {
+    MemoryRegionSection* section = get_memory_region_section(s->cpu);
+    for(int i=0;i<10;i++) {
+        if (!section->size) break;
+        if(section->mr->ram  ) {
+            machine_specific_memory_dump(section->mr);
+        }
+        section++;
+    }
+}
                 cpu_abort(CPU(s->cpu),
                           "Lockup: can't escalate %d to HardFault "
                           "(current priority %d)\n", irq, running);
diff --git a/system/physmem.c b/system/physmem.c
index 9a3b3a7636..a7226b30c3 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -3897,3 +3897,8 @@ bool ram_block_discard_is_required(void)
     return qatomic_read(&ram_block_discard_required_cnt) ||
            qatomic_read(&ram_block_coordinated_discard_required_cnt);
 }
+
+MemoryRegionSection *get_memory_region_section(ARMCPU *cpu);
+MemoryRegionSection *get_memory_region_section(ARMCPU *cpu) {
+    return ((CPUState*)cpu)->cpu_ases->memory_dispatch ->map .sections;
+}

```

# gdb
多分これが一番はやい？

abortしたらこんな感じになると思う
```
(gdb) bt 
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x00007ffff674a6d3 in __pthread_kill_internal (threadid=<optimized out>, signo=6) at pthread_kill.c:78
#2  0x00007ffff66f1c4e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3  0x00007ffff66d9902 in __GI_abort () at abort.c:79
#4  0x0000555556077051 in cpu_abort (cpu=0x555557b7bd70, fmt=0x5555565ad260 "Lockup: can't escalate %d to HardFault (current priority %d)\n") at ../qemu/cpu-target.c:372
#5  0x0000555556005b15 in do_armv7m_nvic_set_pending (opaque=0x555557afb2d0, irq=3, secure=false, derived=false) at ../qemu/hw/intc/armv7m_nvic.c:661
#6  0x0000555556005ba2 in armv7m_nvic_set_pending (s=0x555557afb2d0, irq=12, secure=false) at ../qemu/hw/intc/armv7m_nvic.c:679
#7  0x0000555555f931d8 in arm_v7m_cpu_do_interrupt (cs=0x555557b7bd70) at ../qemu/target/arm/tcg/m_helper.c:2358
#8  0x00005555560c5fa2 in cpu_handle_exception (cpu=0x555557b7bd70, ret=0x7fff6fdff44c) at ../qemu/accel/tcg/cpu-exec.c:758
#9  0x00005555560c67ef in cpu_exec_loop (cpu=0x555557b7bd70, sc=0x7fff
...
```

大きさであたりをつけて
```
(gdb) set $i=0
(gdb) while $i < 10
 >p/x ((CPUState*)s->cpu)->cpu_ases->memory_dispatch->map ->sections[$i].size 
 >set $i=$i+1
 >end
$425 = 0x10000000000000000
$426 = 0x20000
$427 = 0x8000
$428 = 0x2000000
$429 = 0x70000
$430 = 0x400
$431 = 0x20
$432 = 0x20
$433 = 0x400
$434 = 0x14
```

ダンプする
```
(gdb) p/x ((CPUState*)s->cpu)->cpu_ases->memory_dispatch->map ->sections[2].mr->ram_block->host
$435 = 0x7ffff4400000
(gdb) dump binary memory memory_dump.bin 0x7ffff4400000 (0x7ffff4400000 + 0x8000)
(gdb) shell od -Ax -tx1z memory_dump.bin | head -5
000000 d5 00 00 00 ca 02 00 00 95 01 00 00 90 01 00 00  >................<
000010 03 00 00 00 00 00 00 00 c4 02 00 00 96 01 00 00  >................<
000020 94 01 00 00 92 01 00 00 11 22 33 44 55 66 77 88  >........."3DUfw.<
000030 99 aa bb cc dd ee ff 00 40 00 4d 00 40 00 0c 00  >........@.M.@...<
000040 bd 04 00 00 8d 04 00 00 00 6c dc 02 00 12 7a 00  >.........l....z.<

```