feat: lunadbg GDB plugin to ease kernel debugging process.
authorMinep <lunaixsky@qq.com>
Sun, 5 Nov 2023 17:28:58 +0000 (17:28 +0000)
committerMinep <lunaixsky@qq.com>
Sun, 5 Nov 2023 17:35:09 +0000 (17:35 +0000)
fix: rewrite mem_unmap for correctness and robustness
fix: offset in divisor cause system timer running a bit slow than expected.
fix: preventing gcc to put everything into a single loadable section when compiling user-space program
fix: nullptr risk when printing kernel stack trace

20 files changed:
README.md
lunaix-os/.gitignore
lunaix-os/hal/timer/apic_timer.c
lunaix-os/includes/lunaix/mm/region.h
lunaix-os/includes/lunaix/timer.h
lunaix-os/kernel/debug/trace.c
lunaix-os/kernel/mm/mmap.c
lunaix-os/kernel/mm/region.c
lunaix-os/kernel/process/process.c
lunaix-os/kernel/process/sched.c
lunaix-os/kernel/time/clock.c
lunaix-os/kernel/time/timer.c
lunaix-os/scripts/gdb/gdbinit.py [new file with mode: 0644]
lunaix-os/scripts/gdb/install_lunadbg [new file with mode: 0644]
lunaix-os/scripts/gdb/lunadbg/__init__.py [new file with mode: 0644]
lunaix-os/scripts/gdb/lunadbg/commands.py [new file with mode: 0644]
lunaix-os/scripts/gdb/lunadbg/proc_table_dump.py [new file with mode: 0644]
lunaix-os/scripts/gdb/lunadbg/region_dump.py [new file with mode: 0644]
lunaix-os/scripts/gdb/lunadbg/utils.py [new file with mode: 0644]
lunaix-os/usr/link-usr.ld

index 064c6bee504a742e24e0f461083e585933fa73c2..4acc34645076e3f21bc21c550749049b516fcc10 100644 (file)
--- a/README.md
+++ b/README.md
@@ -45,6 +45,9 @@ LunaixOS - 一个简单的,详细的,POSIX兼容的(但愿!),带有
 + 远程GDB串口调试 (COM1@9600Bd)
 + 用户程序加载与执行
 + 动态链接 (WIP)
++ 通用设备抽象层
++ 通用图形设备抽象层
+  + 标准VGA实现
 
 已经测试过的环境:
 
@@ -97,7 +100,7 @@ LunaixOS - 一个简单的,详细的,POSIX兼容的(但愿!),带有
 
 **※:由于在`-O2`模式下,GCC会进行CSE优化,这导致LunaixOS会出现一些非常奇怪、离谱的bug,从而影响到基本运行。具体原因有待调查。**
 
-## 运行,分支以及Issue
+## 运行,分支以及 Issue
 
 运行该操作系统需要一个虚拟磁盘镜像,可以使用如下命令快速创建一个:
 
@@ -135,6 +138,20 @@ qemu-img create -f vdi machine/disk0.vdi 128M
 
 正常,**因为Bochs不支持SATA**。请使用QEMU或VirtualBox。
 
+## 调试 Lunaix 内核
+
+除了[附录4:串口GDB远程调试](#appendix4)描述的一种用于实机调试的方式以外。LunaixOS还提供了LunaDBG调试套件。这是一个GDB客户端插件,包含了对GDB原生命令集的一些扩充,主要用于改善与简化内核调试的过程。目前包含以下几个命令:
+
++ `vmrs [pid]` 列举进程`<pid>`的内存区域图(Memory Regions),如果`<pid>`未指定,则默认为正在运行的进程(smp=1)。
++ `proc [pid]` 打印进程`<pid>`的进程控制块状态,如果`<pid>`未指定,则默认为正在运行的进程(smp=1)。
++ `proc_table` 列举所有非终止的进程以及他们的状态。
+
+该插件可以通过运行以下命令来进行安装:
+
+```shell
+./scripts/gdb/install_lunadbg
+```
+
 ## 参考教程
 
 **没有!!** 本教程以及该操作系统均为原创,没有基于任何市面上现行的操作系统开发教程,且并非是基于任何的开源内核的二次开发。
@@ -172,8 +189,6 @@ qemu-img create -f vdi machine/disk0.vdi 128M
 
 + *Computer System - A Programmer's Perspective Third Edition (CS:APP)* (Bryant, R & O'Hallaron, D)
 + *Modern Operating System* (Tanenbaum, A)
-+ 《汇编语言》(王爽) - 用于入门Intel语法的x86汇编(对于AT&T语法,推荐阅读CS:APP)
-+ ~~《微机原理与接口技术》 - 用于大致了解x86架构的微机体系(更加细致的了解可以阅读Intel Manual)~~ (已过时,推荐阅读CS:APP)
 
 #### 网站
 
@@ -339,7 +354,7 @@ make all-gcc &&\
 + (如可能)提供错误发生时,EIP附近的指令(精确到函数)。如果使用`make all-debug`,会提供`build/kdump.txt`,你可以在这里面定位。或者也可以直接`objdump`
 + (如可能)虚拟内存映射信息(QEMU下可使用`info mem`查看)。
 
-## 附录4:串口GDB远程调试
+## 附录4:串口GDB远程调试<a id="appendix4"></a>
 
 LunaixOS内核集成了最基本的GDB远程调试服务器。可通过串口COM1在9600波特率上与之建立链接。但是,在将GDB与内核链接起来之前,还需要让内核处在调试模式下。
 
index 31f081b6273c44b7ecb4165bd914acc3257786fd..d85c7e515cc460599bf5ba3a0044e69f882418fb 100644 (file)
@@ -9,6 +9,7 @@ machine/
 draft/
 iso_inspect/
 unused/
+__pycache__/
 
 .gdb_history
 
index 8ec8747982c384be5350479c3b8ebfd961acc58f..97f97440942ee7b69126712324561de4caf8e842 100644 (file)
@@ -137,14 +137,13 @@ apic_timer_init(struct hwtimer* timer, u32_t hertz, timer_tick_cb timer_cb)
     // cleanup
     isrm_ivfree(iv_timer);
 
+    ticks_t tphz = base_freq / frequency;
+    timer->base_freq = base_freq;
+    apic_write_reg(APIC_TIMER_ICR, tphz);
+
     apic_write_reg(
       APIC_TIMER_LVT,
       LVT_ENTRY_TIMER(isrm_ivexalloc(apic_timer_tick_isr), LVT_TIMER_PERIODIC));
-
-    timer->base_freq = base_freq;
-
-    ticks_t tphz = base_freq / frequency;
-    apic_write_reg(APIC_TIMER_ICR, tphz);
 }
 
 struct hwtimer*
index 99e9990a3e306c51e727ffd019c5c238e700954d..c0ecd6196fc48e84729ba7148cffe2cbd156fdb4 100644 (file)
@@ -22,6 +22,9 @@ struct mm_region*
 region_get(vm_regions_t* lead, unsigned long vaddr);
 
 void
-region_copy(struct proc_mm* src, struct proc_mm* dest);
+region_copy_mm(struct proc_mm* src, struct proc_mm* dest);
+
+struct mm_region*
+region_dup(struct mm_region* origin);
 
 #endif /* __LUNAIX_REGION_H */
index d1b78450a821c4f6c1691c0d856c5e22998f612f..b93941f76b5ab6945d3a906464d98893a6cb50dd 100644 (file)
@@ -5,7 +5,7 @@
 #include <lunaix/time.h>
 #include <sys/interrupts.h>
 
-#define SYS_TIMER_FREQUENCY_HZ 1024
+#define SYS_TIMER_FREQUENCY_HZ 1000
 
 #define TIMER_MODE_PERIODIC 0x1
 
index 1235884c68704417f821f36501fa8249133fd2de..1cf9ae34d37295a7251058d80813c978c7e84e12 100644 (file)
@@ -148,7 +148,8 @@ trace_printswctx(const isr_param* p, char* direction)
           p->execp->vector,
           p->execp->err_code);
 
-    trace_print_code_entry(sym->pc, p->execp->eip, ksym_getstr(sym));
+    ptr_t sym_pc = sym ? sym->pc : p->execp->eip;
+    trace_print_code_entry(sym_pc, p->execp->eip, ksym_getstr(sym));
 }
 
 void
index 3ca77f272ff5d174c1670aee59f9bea9fff1bac0..afb4246b67a77061f059d29c4316ff05df0c83ac 100644 (file)
@@ -94,7 +94,7 @@ mem_map(void** addr_out,
             if (pos->start > found_loc && avail_space > param->mlen) {
                 goto found;
             }
-            found_loc = pos->end + PG_SIZE;
+            found_loc = pos->end + MEM_PAGE;
         }
 
         last_end = pos->end;
@@ -238,6 +238,82 @@ mem_unmap_region(ptr_t mnt, struct mm_region* region)
     region_release(region);
 }
 
+// Case: head inseted, tail inseted
+#define CASE_HITI(vmr, addr, len)                                              \
+    ((vmr)->start <= (addr) && ((addr) + (len)) <= (vmr)->end)
+
+// Case: head inseted, tail extruded
+#define CASE_HITE(vmr, addr, len)                                              \
+    ((vmr)->start <= (addr) && ((addr) + (len)) > (vmr)->end)
+
+// Case: head extruded, tail inseted
+#define CASE_HETI(vmr, addr, len)                                              \
+    ((vmr)->start > (addr) && ((addr) + (len)) <= (vmr)->end)
+
+// Case: head extruded, tail extruded
+#define CASE_HETE(vmr, addr, len)                                              \
+    ((vmr)->start > (addr) && ((addr) + (len)) > (vmr)->end)
+
+static void
+__unmap_overlapped_cases(struct mm_region* vmr, ptr_t* addr, size_t* length)
+{
+    // seg start, umapped segement start
+    ptr_t seg_start = *addr, umps_start = 0;
+
+    // seg len, umapped segement len
+    size_t seg_len = *length, umps_len = 0;
+
+    size_t displ = 0, shrink = 0;
+
+    if (CASE_HITI(vmr, seg_start, seg_len)) {
+        size_t new_start = seg_start + seg_len;
+        if (new_start < vmr->end) {
+            struct mm_region* region = region_dup(vmr);
+            if (region->mfile) {
+                size_t f_shifted = new_start - region->start;
+                region->foff += f_shifted;
+                region->flen = MAX(region->flen, f_shifted) - f_shifted;
+            }
+            region->start = new_start;
+            llist_insert_after(&vmr->head, &region->head);
+        }
+
+        shrink = vmr->end - seg_start;
+        umps_len = shrink;
+        umps_start = seg_start;
+    } else if (CASE_HITE(vmr, seg_start, seg_len)) {
+        shrink = vmr->end - seg_start;
+        umps_len = shrink;
+        umps_start = seg_start;
+    } else if (CASE_HETI(vmr, seg_start, seg_len)) {
+        displ = seg_len - (vmr->start - seg_start);
+        umps_len = displ;
+        umps_start = vmr->start;
+    } else if (CASE_HETE(vmr, seg_start, seg_len)) {
+        shrink = vmr->end - vmr->start;
+        umps_len = shrink;
+        umps_start = vmr->start;
+    } else {
+        fail("invalid case");
+    }
+
+    vmr->start += displ;
+    vmr->end -= shrink;
+
+    if (vmr->start >= vmr->end) {
+        llist_delete(&vmr->head);
+        region_release(vmr);
+    } else if (vmr->mfile) {
+        vmr->foff += displ;
+        vmr->flen = MAX(vmr->flen, displ) - displ;
+    }
+
+    *addr = umps_start + umps_len;
+
+    size_t ump_len = *addr - seg_start;
+    *length = MAX(seg_len, ump_len) - ump_len;
+}
+
 int
 mem_unmap(ptr_t mnt, vm_regions_t* regions, ptr_t addr, size_t length)
 {
@@ -247,42 +323,17 @@ mem_unmap(ptr_t mnt, vm_regions_t* regions, ptr_t addr, size_t length)
 
     llist_for_each(pos, n, regions, head)
     {
-        if (pos->start <= cur_addr && pos->end >= cur_addr) {
+        u32_t l = pos->start - cur_addr;
+        if ((pos->start <= cur_addr && cur_addr < pos->end) || l <= length) {
             break;
         }
     }
 
-    while (&pos->head != regions && cur_addr >= pos->start) {
-        u32_t l = pos->end - cur_addr;
-        pos->end = cur_addr;
-
-        if (l > length) {
-            // unmap cause discontinunity in a memory region -  do split
-            struct mm_region* region = valloc(sizeof(struct mm_region));
-            *region = *pos;
-            region->start = cur_addr + length;
-            llist_insert_after(&pos->head, &region->head);
-            l = length;
-        }
-
-        mem_sync_pages(mnt, pos, cur_addr, l, 0);
-
-        for (size_t i = 0; i < l; i += PG_SIZE) {
-            ptr_t pa = vmm_del_mapping(mnt, cur_addr + i);
-            if (pa) {
-                pmm_free_page(pos->proc_vms->pid, pa);
-            }
-        }
-
+    while (&pos->head != regions && length) {
         n = container_of(pos->head.next, typeof(*pos), head);
-        if (pos->end == pos->start) {
-            llist_delete(&pos->head);
-            region_release(pos);
-        }
+        __unmap_overlapped_cases(pos, &cur_addr, &length);
 
         pos = n;
-        length -= l;
-        cur_addr += length;
     }
 
     return 0;
index 6340cfbb9d1768632abda81f34352f62898b4d26..f47baa749efd493fd560a9c1154200c75ff13306 100644 (file)
@@ -3,6 +3,8 @@
 #include <lunaix/mm/valloc.h>
 #include <lunaix/spike.h>
 
+#include <sys/mm/mempart.h>
+
 #include <klibc/string.h>
 
 struct mm_region*
@@ -24,7 +26,21 @@ region_create_range(ptr_t start, size_t length, u32_t attr)
     struct mm_region* region = valloc(sizeof(struct mm_region));
     *region = (struct mm_region){ .attr = attr,
                                   .start = start,
-                                  .end = PG_ALIGN(start + length - 1) };
+                                  .end = ROUNDUP(start + length, MEM_PAGE) };
+    return region;
+}
+
+struct mm_region*
+region_dup(struct mm_region* origin)
+{
+    struct mm_region* region = valloc(sizeof(struct mm_region));
+    *region = *origin;
+
+    if (region->mfile) {
+        vfs_ref_file(region->mfile);
+    }
+
+    llist_init_head(&region->head);
     return region;
 }
 
@@ -36,20 +52,20 @@ region_add(vm_regions_t* lead, struct mm_region* vmregion)
         return;
     }
 
+    struct mm_region *pos = (struct mm_region*)lead->next,
+                     *n = list_entry(pos->head.next, struct mm_region, head);
     ptr_t cur_end = 0;
-    struct mm_region *pos = (struct mm_region*)lead,
-                     *n = list_entry(lead->next, struct mm_region, head);
-    do {
-        if (vmregion->start > cur_end && vmregion->end < n->start) {
+
+    llist_for_each(pos, n, lead, head)
+    {
+        if (vmregion->start >= cur_end && vmregion->end <= pos->start) {
             break;
         }
-        cur_end = n->end;
-        pos = n;
-        n = list_entry(n->head.next, struct mm_region, head);
-    } while ((ptr_t)&n->head != (ptr_t)lead);
+        cur_end = pos->end;
+    }
 
     // XXX caution. require mm_region::head to be the lead of struct
-    llist_insert_after(&pos->head, &vmregion->head);
+    llist_append(&pos->head, &vmregion->head);
 }
 
 void
@@ -82,7 +98,7 @@ region_release_all(vm_regions_t* lead)
 }
 
 void
-region_copy(struct proc_mm* src, struct proc_mm* dest)
+region_copy_mm(struct proc_mm* src, struct proc_mm* dest)
 {
     struct mm_region *pos, *n, *dup;
 
@@ -118,7 +134,7 @@ region_get(vm_regions_t* lead, unsigned long vaddr)
 
     llist_for_each(pos, n, lead, head)
     {
-        if (pos->start <= vaddr && vaddr <= pos->end) {
+        if (pos->start <= vaddr && vaddr < pos->end) {
             return pos;
         }
     }
index 2a4bdb452c8314fbda85776c56fdaaf6fe2bea58..bdd904917d2d2a8c6dd7b0032cf5971be8b70648 100644 (file)
@@ -218,7 +218,7 @@ dup_proc()
     }
 
     __copy_fdtable(pcb);
-    region_copy(&__current->mm, &pcb->mm);
+    region_copy_mm(&__current->mm, &pcb->mm);
 
     /*
      *  store the return value for forked process.
index 31a94ee08f3ce7f8fe6be03d0b81084cf7b4a7e4..aa75714b0dcc9aeb6378a61d79ac48ef4264a9bb 100644 (file)
@@ -2,8 +2,8 @@
 #include <sys/interrupts.h>
 #include <sys/mm/mempart.h>
 
-#include <sys/cpu.h>
 #include <hal/intc.h>
+#include <sys/cpu.h>
 
 #include <lunaix/fs/taskfs.h>
 #include <lunaix/mm/cake.h>
@@ -112,7 +112,7 @@ check_sleepers()
 {
     struct proc_info* leader = sched_ctx._procs[0];
     struct proc_info *pos, *n;
-    time_t now = clock_systime();
+    time_t now = clock_systime() / 1000;
     llist_for_each(pos, n, &leader->sleep.sleepers, sleep.sleepers)
     {
         if (proc_terminated(pos)) {
@@ -191,12 +191,14 @@ __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
         return 0;
     }
 
+    time_t systime = clock_systime() / 1000;
+
     if (__current->sleep.wakeup_time) {
-        return (__current->sleep.wakeup_time - clock_systime()) / 1000U;
+        return (__current->sleep.wakeup_time - systime);
     }
 
     struct proc_info* root_proc = sched_ctx._procs[0];
-    __current->sleep.wakeup_time = clock_systime() + seconds;
+    __current->sleep.wakeup_time = systime + seconds;
 
     if (llist_empty(&__current->sleep.sleepers)) {
         llist_append(&root_proc->sleep.sleepers, &__current->sleep.sleepers);
@@ -213,7 +215,7 @@ __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
 __DEFINE_LXSYSCALL1(unsigned int, alarm, unsigned int, seconds)
 {
     time_t prev_ddl = __current->sleep.alarm_time;
-    time_t now = clock_systime();
+    time_t now = clock_systime() / 1000;
 
     __current->sleep.alarm_time = seconds ? now + seconds : 0;
 
@@ -222,7 +224,7 @@ __DEFINE_LXSYSCALL1(unsigned int, alarm, unsigned int, seconds)
         llist_append(&root_proc->sleep.sleepers, &__current->sleep.sleepers);
     }
 
-    return prev_ddl ? (prev_ddl - now) / 1000 : 0;
+    return prev_ddl ? (prev_ddl - now) : 0;
 }
 
 __DEFINE_LXSYSCALL1(void, exit, int, status)
index 2bf61d4f48700fed442252b8a694c51c15598405..3170731b842c340398227f33f898a61e2baf4060 100644 (file)
@@ -67,7 +67,12 @@ clock_systime()
 
     ticks_t t = hwtimer_current_systicks();
     ticks_t tu = systimer->running_freq / 1000;
-    return t / (tu + 1);
+
+    if (unlikely(!tu)) {
+        return t;
+    }
+
+    return t / (tu);
 }
 
 void
index 8f368df59ce83889f6b2ccbef65fbf1456e1a37a..e48c40cd5c4a42a1028ba3748260eaee03e5e4c8 100644 (file)
@@ -54,7 +54,7 @@ timer_init()
 
     timer_ctx->base_frequency = hwtimer_base_frequency();
 
-    sched_ticks = SYS_TIMER_FREQUENCY_HZ / 1000 * SCHED_TIME_SLICE;
+    sched_ticks = (SYS_TIMER_FREQUENCY_HZ * SCHED_TIME_SLICE) / 1000;
     sched_ticks_counter = 0;
 }
 
diff --git a/lunaix-os/scripts/gdb/gdbinit.py b/lunaix-os/scripts/gdb/gdbinit.py
new file mode 100644 (file)
index 0000000..05bdabb
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import sys
+from os import path
+
+
+directory, file = path.split(__file__)
+directory       = path.expanduser(directory)
+directory       = path.abspath(directory)
+
+sys.path.append(directory)
+
+import lunadbg
\ No newline at end of file
diff --git a/lunaix-os/scripts/gdb/install_lunadbg b/lunaix-os/scripts/gdb/install_lunadbg
new file mode 100644 (file)
index 0000000..5c0de1d
--- /dev/null
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+echo "source \"${SCRIPT_DIR}/gdbinit.py\"" >> ~/.gdbinit
\ No newline at end of file
diff --git a/lunaix-os/scripts/gdb/lunadbg/__init__.py b/lunaix-os/scripts/gdb/lunadbg/__init__.py
new file mode 100644 (file)
index 0000000..5a1955d
--- /dev/null
@@ -0,0 +1,3 @@
+from .commands import load_commands
+
+load_commands()
\ No newline at end of file
diff --git a/lunaix-os/scripts/gdb/lunadbg/commands.py b/lunaix-os/scripts/gdb/lunadbg/commands.py
new file mode 100644 (file)
index 0000000..698ea85
--- /dev/null
@@ -0,0 +1,8 @@
+from .region_dump import MemoryRegionDump
+from .proc_table_dump import ProcessDump, ProcessTableDump
+
+
+def load_commands():
+    MemoryRegionDump()
+    ProcessTableDump()
+    ProcessDump()
\ No newline at end of file
diff --git a/lunaix-os/scripts/gdb/lunadbg/proc_table_dump.py b/lunaix-os/scripts/gdb/lunadbg/proc_table_dump.py
new file mode 100644 (file)
index 0000000..8897607
--- /dev/null
@@ -0,0 +1,76 @@
+import gdb
+from .utils import pid_argument
+
+class ProcessHelper:
+    PS_READY   = 0
+    PS_RUNNING = 1
+    PS_TERMNAT = 2
+    PS_DESTROY = 4
+    PS_PAUSED  = 8
+    PS_BLOCKED = 16
+    PS_CREATED = 32
+
+    def get_state(proc: gdb.Value):
+        state_t = proc["state"]
+        if (state_t == ProcessHelper.PS_READY):
+            return "ready"
+        if (state_t == ProcessHelper.PS_RUNNING):
+            return "running"
+        if (state_t & (ProcessHelper.PS_TERMNAT | ProcessHelper.PS_DESTROY)):
+            return "terminated"
+        if (state_t & ProcessHelper.PS_BLOCKED):
+            return "blocked"
+        if (state_t & ProcessHelper.PS_PAUSED):
+            return "paused"
+        
+    def process_at(pid):
+        return gdb.parse_and_eval(pid_argument(pid))
+
+    @staticmethod    
+    def pp_process(proc: gdb.Value):
+        print("  pid:", proc["pid"])
+        print("  pgid:", proc["pgid"])
+        if proc["parent"] == 0:
+            print(" root process")
+        else:
+            print("  ppid:", proc["parent"]["pid"])
+        print("  page table:", proc["page_table"])
+
+        print("  state:", ProcessHelper.get_state(proc))
+        print("  created: +%dms"%(proc["created"]))
+        print("  saved context:")
+        print("     %s"%(proc["intr_ctx"].dereference()
+                         .format_string(max_depth=3, format='x')
+                         .replace('\n', '\n     ')))
+
+
+class ProcessDump(gdb.Command):
+    """Dump the state of Lunaix PCB"""
+    def __init__(self) -> None:
+        super().__init__("proc", gdb.COMMAND_USER)
+
+    def invoke(self, argument: str, from_tty: bool) -> None:
+        argument = pid_argument(argument)
+
+        proc = gdb.parse_and_eval(argument)
+
+        ProcessHelper.pp_process(proc)
+
+class ProcessTableDump(gdb.Command):
+    """Dump the state of Lunaix process table"""
+    def __init__(self) -> None:
+        super().__init__("proc_table", gdb.COMMAND_USER)
+
+    def invoke(self, argument: str, from_tty: bool) -> None:
+        sched_context = gdb.parse_and_eval("sched_ctx")
+        total_entries = sched_context["ptable_len"]
+        print("inited entries: %d"%(total_entries))
+        print("scheduled pid: %d"%(sched_context["procs_index"]))
+        print("Process Table:")
+
+        for i in range(0, total_entries):
+            p = ProcessHelper.process_at(i)
+            if (p == 0):
+                continue
+            state = ProcessHelper.get_state(p)
+            print("   pid:%02d [%s]"%(i, state))
\ No newline at end of file
diff --git a/lunaix-os/scripts/gdb/lunadbg/region_dump.py b/lunaix-os/scripts/gdb/lunadbg/region_dump.py
new file mode 100644 (file)
index 0000000..92ee65d
--- /dev/null
@@ -0,0 +1,49 @@
+import gdb
+from .utils import pid_argument
+
+class MemoryRegionDump(gdb.Command):
+    """Dump virtual memory regions associated with a process"""
+    def __init__(self) -> None:
+        super().__init__("vmrs", gdb.COMMAND_USER)
+
+    def invoke(self, argument: str, from_tty: bool) -> None:
+        argument = pid_argument(argument)
+        
+        pid = gdb.parse_and_eval(f"{argument}->pid")
+
+        argument = f"&{argument}->mm.regions"
+        val = gdb.parse_and_eval(argument)
+        head = val
+
+        region_t = gdb.lookup_type("struct mm_region").pointer()
+        
+        print("VMRS (pid: %d)"%(pid))
+
+        i = 0
+        while(val["next"] != head):
+            region = val["next"].cast(region_t)
+            print(f"VMR #{i}:")
+            print( "  0x%x...0x%x [0x%x]"%(
+                region['start'], region['end'], 
+                region['end'] - region['start']))
+            
+            attr = region["attr"]
+            attr_str = []
+            if (attr & (1 << 2)):
+                attr_str.append("R")
+            if (attr & (1 << 3)):
+                attr_str.append("W")
+            if (attr & (1 << 4)):
+                attr_str.append("X")
+            print( "  attr: 0x%x (%s)"%(attr, "".join(attr_str)))
+            
+            file = region["mfile"]
+            if file == 0:
+                print( "  anonymous region")
+            else:
+                print( "  file mapped:")
+                print( "     dnode: %s @0x%x"%(file["dnode"]["name"]["value"].string(), file))
+                print( "     frange: 0x%x+0x%x"%(region["foff"], region["flen"]))
+
+            val = val["next"]
+            i+=1
diff --git a/lunaix-os/scripts/gdb/lunadbg/utils.py b/lunaix-os/scripts/gdb/lunadbg/utils.py
new file mode 100644 (file)
index 0000000..b48adee
--- /dev/null
@@ -0,0 +1,6 @@
+
+def pid_argument(argument):
+    if not argument:
+        return "__current"
+    else:
+        return f"sched_ctx._procs[({argument})]"
\ No newline at end of file
index 27a50201ac6f63948944c7082a9c73f00f8d1c42..ab77bb42f0c1b9f24aa16a473ebec4a6160fceb4 100644 (file)
@@ -3,19 +3,19 @@ ENTRY(_start)
 SECTIONS {
     . = 0x400000;
 
-    .text : {
+    .text BLOCK(4K) : {
         *(.text)
     }
 
-    .data : {
+    .data BLOCK(4K) : {
         *(.data)
     }
 
-    .ro.data : {
+    .ro.data BLOCK(4K) : {
         *(.ro.data)
     }
 
-    .bss : {
+    .bss BLOCK(4K) : {
         *(.bss)
     }
 }