====== Piotr JaroszyĆski: Usermode debugging under Linux ======
===== Week 8 [ Jul 12 - Jul 18 2010 ] =====
==== valgrind ====
I wasn't supposed to work on valgrind related stuff, but the following report keeps nagging me:
==31509== 360 bytes in 1 blocks are still reachable in loss record 4 of 5
==31509== at 0x402C2E: realloc (malloc.c:316)
==31509== by 0x402DCE: malloc (malloc.c:351)
==31509== by 0x402DDC: zalloc (malloc.c:382)
==31509== by 0x404FF8: alloc_netdev (netdevice.c:329)
==31509== by 0x404185: alloc_etherdev (ethernet.c:186)
==31509== by 0x400041: tap_probe (tap.c:142)
==31509== by 0x40FE34: linux_probe (linux.c:42)
==31509== by 0x4020A8: probe_devices (device.c:47)
==31509== by 0x40BB42: startup (init.c:67)
==31509== by 0x40229E: main (main.c:48)
See, ''tap_probe()'' is part of the tap driver that I wrote so that makes me look bad ;)
I have the issue half-fixed, but while debugging it I stumbled upon another bug, namely false reports like:
==31633== Invalid read of size 8
==31633== at 0x4042CD: ipv4_create_routes (ipv4.c:593)
==31633== by 0x40124F: apply_settings (settings.c:374)
==31633== by 0x401869: register_settings (settings.c:451)
==31633== by 0x40FE8C: smbios_init (smbios_settings.c:139)
==31633== by 0x40BAF0: initialise (init.c:48)
==31633== by 0x402299: main (main.c:47)
==31633== Address 0x617140 is 0 bytes inside data symbol "ipv4_miniroutes"
''ipv4_miniroutes'' is a file-scoped ''struct list_head'' and the supposedly bad code is:
list_for_each_entry_safe ( miniroute, tmp, &ipv4_miniroutes, list )
To make things more complicated it only happened with ''DEBUG=settings''.
All this didn't make much sense until I looked at ''tap.linux.tmp.map'' and found out what symbol is before ''ipv4_miniroutes'':
0000000000617190 l O .data 0000000000000010 free_blocks
00000000006171a0 g O .data 0000000000000010 .hidden ipv4_miniroutes
Now I knew exactly where to look, ''core/malloc.c'':
static inline void valgrind_make_blocks_noaccess ( void )
{
struct memory_block *block, *tmp;
if ( RUNNING_ON_VALGRIND > 0 ) {
list_for_each_entry_safe ( block, tmp, &free_blocks, list )
VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) );
VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) );
}
}
I got lazy and copy-n-pasted the inner-loop instruction to mark the last item on the list - i.e. ''free_blocks'' as ''NOACCESS''.
The problem is that ''free_blocks'' is not a ''struct memory_block'', but ''struct list_head''
and hence the ''NOACCESS'' was marking wrong chunk of the memory, also including part of the ''ipv4_miniroutes''. Fix:
- VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) );
+ VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) );
==== drivers in userspace ====
Working on it while I'm not distracted by other things ;)