Hello, I'm using gdb (6.5) to analyse a Linux kernel kdump (really an ELF core file), and I find that a simple script is awwwfully slow. Here is an example: define cntmaps shell date set $map = vmlist set $gcount = 0 while $map != 0 set $gcount = $gcount + 1 set $map = $map->next end printf "vmlist count: %d\n", $gcount shell date end (gdb) cntmaps Thu Oct 5 13:44:04 CEST 2006 vmlist count: 99 Thu Oct 5 13:44:14 CEST 2006 So it takes about 10 seconds to walk a list with ~100 elements, without doing anything really useful (the host is a 2GHz dual core!). I have another script that does more complex processing with the same list, and it takes about 12 minutes to complete! It's the lsmaps macro below, which ends up calling the vmap macro 2381 times. So I rebuilt gdb with profiling (-pg), attached is the complete output from gprof after running lsmaps in batch mode. A quick look suggests that some symbol lookups are problematic, and I suspect that gdb easily ends up doing linear searches in some big table (I'm working on a Linux kernel with full debug infos). Any suggestion for performance improvement? Maybe gdb could use hash tables to speed up things a bit? :-) Cheers, -- saffroy@gmail.com # a few useful(?) macros for x86-64 VMM hacks # useful constants set $PAGE_SIZE = (1<<12) set $__PHYSICAL_MASK = (1 << 46)-1 set $PTE_MASK = ~($PAGE_SIZE-1) & $__PHYSICAL_MASK set $__PAGE_OFFSET = 0xffff810000000000 set $_PAGE_PSE = 0x80 define vmap set $addr = (long)$arg0 # index in each of the 4 levels of page directories set $pgd = $addr >> 39 & (1<<9)-1 set $pud = $addr >> 30 & (1<<9)-1 set $pmd = $addr >> 21 & (1<<9)-1 set $pte = $addr >> 12 & (1<<9)-1 # offset in page set $off = $addr & (1<<12)-1 #printf "%03x %03x %03x %03x %03x\n", $pgd, $pud, $pmd, $pte, $off set $pgd_off = (pgd_t *) &init_level4_pgt + $pgd #printf "pgd_off: %lx pgd: %lx\n", $pgd_off, (long)$pgd_off->pgd set $pgd_page = ((long)$pgd_off->pgd & $PTE_MASK) + $__PAGE_OFFSET #printf "pgd_page: %lx\n", $pgd_page set $pud_off = ((pud_t *) $pgd_page) + $pud #printf "pud_off: %lx pud: %lx\n", $pud_off, (long)$pud_off->pud set $pud_page = ((long)$pud_off->pud & $PTE_MASK) + $__PAGE_OFFSET #printf "pud_page: %lx\n", $pud_page set $pmd_off = ((pmd_t *) $pud_page) + $pmd #printf "pmd_off: %lx pmd: %lx\n", $pmd_off, (long)$pmd_off->pmd set $pmd_page = ((long)$pmd_off->pmd & $PTE_MASK) + $__PAGE_OFFSET #printf "pmd_page: %lx\n", $pmd_page if ((long)$pmd_off->pmd & $_PAGE_PSE) != 0 #printf "PSE page! " set $paddr = $pmd_page + ($addr & (1<<21)-1) else set $pte_off = ((pte_t *) $pmd_page) + $pte #printf "pte_off: %lx pte: %lx\n", $pte_off, (long)$pte_off->pte set $pte_page = ((long)$pte_off->pte & $PTE_MASK) + $__PAGE_OFFSET #printf "pte_page: %lx\n", $pte_page set $paddr = $pte_page + $off end #printf "remapped physical addr: %lx\n", $paddr printf "%lx -> %lx\n", $addr, $paddr end define lsmaps set $map = vmlist set $gcount = 0 while $map != 0 if $map->pages != 0 set $vaddr = (long)$map->addr set $count = (long)$map->size / $PAGE_SIZE set $gcount = $gcount + $count -1 while $count > 1 vmap $vaddr set $vaddr = $vaddr + $PAGE_SIZE set $count = $count - 1 end end set $map = $map->next end printf "page count: %d\n", $gcount end