gdb script performance

Jean-Marc Saffroy saffroy@gmail.com
Thu Oct 5 12:16:00 GMT 2006


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: gdb-gprof.txt.bz2
Type: application/octet-stream
Size: 63566 bytes
Desc: 
URL: <http://sourceware.org/pipermail/gdb/attachments/20061005/2f942dac/attachment.obj>


More information about the Gdb mailing list