diff --git a/LKM.svg b/LKM.svg index 6978183..fccb0b4 100644 --- a/LKM.svg +++ b/LKM.svg @@ -19,7 +19,6 @@ inkscape:export-filename="LKM.png" inkscape:export-xdpi="85.330002" inkscape:export-ydpi="85.330002" - viewBox="0 0 2160 1620" version="1.0"> @@ -431,15 +430,15 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="0.30987654" - inkscape:cx="1080" - inkscape:cy="809.99999" - inkscape:current-layer="svg9393" + inkscape:zoom="0.73766078" + inkscape:cx="690.23234" + inkscape:cy="1163.6329" + inkscape:current-layer="layer3" inkscape:document-units="px" - inkscape:window-width="1317" - inkscape:window-height="711" - inkscape:window-x="49" - inkscape:window-y="27" + inkscape:window-width="1873" + inkscape:window-height="1056" + inkscape:window-x="47" + inkscape:window-y="24" showgrid="false" gridtolerance="5" showguides="true" @@ -481,7783 +480,7780 @@ - - - - - - - - - - - - virtual - - - logical - - - - - - - - - - - electronics - - - - I/O - - - - - - memory - - - - CPU - - - HI char devices - - - HI subsystems - - - protocol families - - - sockets access - - - protocols - - - network interface - - - networking - - - Virtual File System - - - block devices - - - storage - - - virtual memory - - - memory access - - - logical memory - - - Page Allocator - - - memory - - - threads - - - processes - - - Scheduler - - - interrupts core - - - CPU specific - - - processing - - - generic HW access - - - system run - - - system - - - functionalities - - - layers - - - interfaces core - - - - Linux kernel map - - - logicalfile systems - + + + + + + + + + + + virtual + + + logical + + + + + + + + + + + electronics + + + + I/O + + + + + + memory + + + + CPU + + + HI char devices + + + HI subsystems + + + protocol families + + + sockets access + + + protocols + + + abstract devicesand HID class drivers - network interface + + + networking + + + Virtual File System + + + block devices + + + storage + + + virtual memory + + + memory access + + + logical memory + + + Page Allocator + + + memory + + + threads + + + processes + + + Scheduler + + + interrupts core + + + CPU specific + + + processing + + + generic HW access + + + system run + + + system + + + functionalities + + + layers + + + interfaces core + + + + Linux kernel map + + + logicalfile systems + abstract devicesand HID class drivers + HI peripheralsdevice drivers - - 2.6.36 - - HI peripheralsdevice drivers + + 2.6.36 + + networkdevice drivers - networkdevice drivers + devicecontrol - - devicecontrol + + disk controllerdrivers - disk controllerdrivers + physical memoryoperations - physical memoryoperations + device accessand bus drivers - device accessand bus drivers + user spaceinterfaces - user spaceinterfaces + hardwareinterfaces - hardwareinterfaces + files & directoriesaccess - files & directoriesaccess + user peripherals - user peripherals + disk controllers - disk controllers + network controllers - network controllers + human interface - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - synchronization - - - Device Model - - - swap - - human interface + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + synchronization + + + Device Model + + + swap + + networkingstorage - networkingstorage + memorymapping - - security - - - bridges - - - debugging - - - page cache - - memorymapping + + security + + + bridges + + + debugging + + + page cache + + socketsplice - - - - sys_init_module - - - timer_interrupt - - jiffies_64 - do_timer - tick_periodic - - context_switch - - alloc_file - - registers - - - RAM - - - MMU - - - I/O ports - - - I/O mem - - - keyboard - - - mouse - - - audio - - - graphics card - - - SCSI - - - SATA - - - DMA - - - Ethernet - - - WiFi - - - APIC - - - physically mapped memory - - - system files - - - copy_from_user - - - - © 2007, 2010 Constantine Shulyupin www.MakeLinux.net/kernel_map - - - - sys_write - - - sys_open - - - sys_execve - - - linux_binfmt - - - vfs_read - - - task_struct - - - usb_driver - - - sys_socketcall - - - socket - - - interrupt - - - sys_fork - - - schedule - - - do_IRQ - - - rq - - - kmalloc - - - kmem_cache - - - vmalloc - - - vmlist - - - page - - - do_page_fault - - - outw - - - cdev - - - /sysfs - - - /dev - - - readw - - - /proc - - - cdev_add - - - oss - - - mousedev - - - kbd - - - i8042_driver - - - psmouse - - - atkbd_drv - - - tty - - - console - - - snd_fops - - - video_fops - - - console_fops - - - vga_con - - - pt_regs - - - __get_free_pages - - - vm_struct - - - sys_mmap - - - /proc/self/maps - - - timer_list - - - do_softirq - - - tasklet_struct - - - request_queue - - - setup_irq - - - init_scsi - - - ext4_file_operations - - - gendisk - - - block_device_operations - - - sys_sync - - - sys_nanosleep - - - schedule_timeout - - - sysfs_ops - - - mm_struct - - - module - - - cdev_map - - - request_region - - - proto_ops - - - socket_file_ops - - - /proc/net/protocols - - - proto - - - tcp_prot - - - inet_stream_ops - - - inet_dgram_ops - - - udp_prot - - - inet_family_ops - - - __sock_create - - - ip_rcv - - - net_device - - - alloc_netdev_mq - - - ieee80211_alloc_hw - - - file_operations - - - sys_syslog - - - aic94xx_init - - - usb_hcd - - - ehci_irq - - - usb_hcd_irq - - - usb_submit_urb - - - ehci_urb_enqueue - - - usb_hcd_giveback_urb - - - pci_driver - - - start_kernel - - - init/main.c - - - run_init_process - - - do_initcalls - - - sys_reboot - - - do_mmap_pgoff - - - sys_brk - - - arch/x86/ - - - irq_desc - - - setup_timer - - - process_timeout - - - activate_task - - - sys_clone - - - sys_vfork - - - file - - - vm_area_struct - - - inode - - - fs/exec.c - - - address_space - - - ip_queue_xmit - - - dev_queue_xmit - - - netif_rx - - - ether_setup - - - ieee80211_xmit - - - ieee80211_rx - - - sd_fops - - - scsi_device - - - scsi_driver - - - sys_socket - - - linux/syscalls.h - - - linux/uaccess.h - - - pci_read - - - pci_write - - - ioremap - - - request_mem_region - - - kernel_power_off - - - kernel_restart - - - writew - - - inw - - - inet_create - - - vfs_write - - - ipw2100_pci_init_one - - - zd1201_probe - - - unix_family_ops - - - sys_mount - - - load_module - - - ext4_get_sb - - - file_system_type - - - get_sb - - - super_block - - - __alloc_pages - - - die - - - /proc/interrupts - - - cli - - - sti - - - switch_to - - - system_call - - - trap_init - - - sys_read - - - do_path_lookup - - - vfs_create - - - kernel/sched.c - - - drivers/net/ - - - show_regs - - - block/ - - - drivers/ - - - drivers/input/ - - - sound/ - - - drivers/media/ - - - init/ - - - kernel/ - - - include/asm/ - - - mm/slob.c - - - /proc/slabinfo - - - ac97_driver - - - usb_storage_driver - - - bus_type - - - device - - - device_driver - - - probe - - - class - - - device_create - - - driver_register - - - drivers/base/ - - - kobject - - - security/ - - - linux/security.h - - - selinux_ops - - - security_ops - - - security_socket_create - - - security_inode_create - - - pci_register_driver - - - ahci_pci_driver - - - libata - - - Scsi_Host - - - may_open - - - create_workqueue - - - alloc_skb - - - alsa - - - inode_operations - - - ramfs_fs_type - - - iscsi_tcp_transport - - - smb_fs_type - - - cifs_file_ops - - - nfs_file_operations - - - sk_buff - - - mm/mmap.c - - - vma_link - - - start_thread - - - find_vma_prepare - - - virt_to_page - - - fb_ops - - - pci_request_regions - - - fb_fops - - - cdev_add - - - register_chrdev - - - kset - - - msleep - - - do_fork - - - kernel_thread - - - current - - - thread_info - - - semaphore - - - workqueue_struct - - - work_struct - - - kthread_create - - - wake_up - - - atomic_t - - - mutex - - - add_timer - - - down_interruptible - - - kswapd - - - do_swap_page - - - fs/ - - - mm/ - - - kernel/ - - - net/ - - - kmem_cache_alloc - - - kernel/ - - - mousedev_handler - - - input_fops - - - get_page_from_freelist - - - wakeup_kswapd - - - try_to_free_pages - - - zone - - - drivers/media/video/ - - - video_device - - - NF_HOOK - - - nf_hooks - - - tcp_transmit_skb - + id="tspan4603">socketsplice + + + + sys_init_module + + + timer_interrupt + + jiffies_64 + do_timer + tick_periodic + + context_switch + + alloc_file + + registers + + + RAM + + + MMU + + + I/O ports + + + I/O mem + + + keyboard + + + mouse + + + audio + + + graphics card + + + SCSI + + + SATA + + + DMA + + + Ethernet + + + WiFi + + + APIC + + + physically mapped memory + + + system files + + + copy_from_user + + + © 2007, 2010 Constantine Shulyupin www.MakeLinux.net/kernel_map + + + + sys_write + + + sys_open + + + sys_execve + + + linux_binfmt + + + vfs_read + + + task_struct + + + usb_driver + + + sys_socketcall + + + socket + + + interrupt + + + sys_fork + + + schedule + + + do_IRQ + + + rq + + + kmalloc + + + kmem_cache + + + vmalloc + + + vmlist + + + page + + + do_page_fault + + + outw + + + cdev + + + /sysfs + + + /dev + + + readw + + + /proc + + + cdev_add + + + oss + + + mousedev + + + kbd + + + i8042_driver + + + psmouse + + + atkbd_drv + + + tty + + + console + + + snd_fops + + + video_fops + + + console_fops + + + vga_con + + + pt_regs + + + __get_free_pages + + + vm_struct + + + sys_mmap + + + /proc/self/maps + + + timer_list + + + do_softirq + + + tasklet_struct + + + request_queue + + + setup_irq + + + init_scsi + + + ext4_file_operations + + + gendisk + + + block_device_operations + + + sys_sync + + + sys_nanosleep + + + schedule_timeout + + + sysfs_ops + + + mm_struct + + + module + + + cdev_map + + + request_region + + + proto_ops + + + socket_file_ops + + + /proc/net/protocols + + + proto + + + tcp_prot + + + inet_stream_ops + + + inet_dgram_ops + + + udp_prot + + + inet_family_ops + + + __sock_create + + + ip_rcv + + + net_device + + + alloc_netdev_mq + + + ieee80211_alloc_hw + + + file_operations + + + sys_syslog + + + aic94xx_init + + + usb_hcd + + + ehci_irq + + + usb_hcd_irq + + + usb_submit_urb + + + ehci_urb_enqueue + + + usb_hcd_giveback_urb + + + pci_driver + + + start_kernel + + + init/main.c + + + run_init_process + + + do_initcalls + + + sys_reboot + + + do_mmap_pgoff + + + sys_brk + + + arch/x86/ + + + irq_desc + + + setup_timer + + + process_timeout + + + activate_task + + + sys_clone + + + sys_vfork + + + file + + + vm_area_struct + + + inode + + + fs/exec.c + + + address_space + + + ip_queue_xmit + + + dev_queue_xmit + + + netif_rx + + + ether_setup + + + ieee80211_xmit + + + ieee80211_rx + + + sd_fops + + + scsi_device + + + scsi_driver + + + sys_socket + + + linux/syscalls.h + + + linux/uaccess.h + + + pci_read + + + pci_write + + + ioremap + + + request_mem_region + + + kernel_power_off + + + kernel_restart + + + writew + + + inw + + + inet_create + + + vfs_write + + + ipw2100_pci_init_one + + + zd1201_probe + + + unix_family_ops + + + sys_mount + + + load_module + + + ext4_get_sb + + + file_system_type + + + get_sb + + + super_block + + + __alloc_pages + + + die + + + /proc/interrupts + + + cli + + + sti + + + switch_to + + + system_call + + + trap_init + + + sys_read + + + do_path_lookup + + + vfs_create + + + kernel/sched.c + + + drivers/net/ + + + show_regs + + + block/ + + + drivers/ + + + drivers/input/ + + + sound/ + + + drivers/media/ + + + init/ + + + kernel/ + + + include/asm/ + + + mm/slob.c + + + /proc/slabinfo + + + ac97_driver + + + usb_storage_driver + + + bus_type + + + device + + + device_driver + + + probe + + + class + + + device_create + + + driver_register + + + drivers/base/ + + + kobject + + + security/ + + + linux/security.h + + + selinux_ops + + + security_ops + + + security_socket_create + + + security_inode_create + + + pci_register_driver + + + ahci_pci_driver + + + libata + + + Scsi_Host + + + may_open + + + create_workqueue + + + alloc_skb + + + alsa + + + inode_operations + + + ramfs_fs_type + + + iscsi_tcp_transport + + + smb_fs_type + + + cifs_file_ops + + + nfs_file_operations + + + sk_buff + + + mm/mmap.c + + + vma_link + + + start_thread + + + find_vma_prepare + + + virt_to_page + + + fb_ops + + + pci_request_regions + + + fb_fops + + + cdev_add + + + register_chrdev + + + kset + + + msleep + + + do_fork + + + kernel_thread + + + current + + + thread_info + + + semaphore + + + workqueue_struct + + + work_struct + + + kthread_create + + + wake_up + + + atomic_t + + + mutex + + + add_timer + + + down_interruptible + + + kswapd + + + do_swap_page + + + fs/ + + + mm/ + + + kernel/ + + + net/ + + + kmem_cache_alloc + + + kernel/ + + + mousedev_handler + + + input_fops + + + get_page_from_freelist + + + wakeup_kswapd + + + try_to_free_pages + + + zone + + + drivers/media/video/ + + + video_device + + + NF_HOOK + + + nf_hooks + + + tcp_transmit_skb + + drivers,registers and interrupts - drivers,registers and interrupts + tcp_sendmsg - tcp_sendmsg + tcp_recvmsg - tcp_recvmsg + udp_sendmsg - udp_sendmsg + udp_recvmsg - - netif_receive_skb - - - linux/netdevice.h - - udp_recvmsg + + netif_receive_skb + + + linux/netdevice.h + + ip_output - ip_output + System Call Interface - - /dev/mem - - - mem_fops - - - mmap_mem - - - sock_ioctl - - - dev_ioctl - - System Call Interface + + /dev/mem + + + mem_fops + + + mmap_mem + + + sock_ioctl + + + dev_ioctl + + linux/device.h - linux/device.h + linux/kobject.h - linux/kobject.h + device_type - device_type + driver_init - - arch/x86/mm/ - - driver_init + + arch/x86/mm/ + + sys_signal - sys_signal + ++ - ++ + request_irq - request_irq + sys_times - sys_times + sys_time - sys_time + sys_gettimeofday - sys_gettimeofday + sys_futex - sys_futex + system callsand system files - system callsand system files + cross-functionalmodules - cross-functionalmodules + sys_mprotect - sys_mprotect + sys_pivot_root - sys_pivot_root + mount_root - mount_root + kernel/signal.c - kernel/signal.c + sys_kill - sys_kill + shm_vm_ops - shm_vm_ops + sys_shmctl - sys_shmctl + sys_shmat - sys_shmat + sys_newfstat - sys_newfstat + sys_select - sys_select + sys_chroot - sys_chroot + kvm_dev_ioctl - kvm_dev_ioctl + kvm - - camera - - kvm + + camera + + interruptcontroller - interruptcontroller + USBcontroller - USBcontroller + PCIcontroller - PCIcontroller + uvc_driver - uvc_driver + sys_ioctl - sys_ioctl + register_netdev - register_netdev + lock_kernel - lock_kernel + kernel_flag - kernel_flag + do_sigaction - do_sigaction + sys_pipe - sys_pipe + sys_fsync - sys_fsync + vfs_fsync - vfs_fsync + bdi_writeback_thread - bdi_writeback_thread + do_writepages - do_writepages + fget - fget + fd - fd + sys_sysfs - sys_sysfs + file_systems - file_systems + sys_flock - sys_flock + sys_mkdir - sys_mkdir + sys_inotify_init - sys_inotify_init + sys_chdir - sys_chdir + vfs_getattr - vfs_getattr + vfs_fstat - vfs_fstat + sys_epoll_create - sys_epoll_create + kmem_cache_alloc - kmem_cache_alloc + inode_permission - inode_permission + notify_change - notify_change + inode_setattr - inode_setattr + sys_chmod - sys_chmod + sys_readv - sys_readv + iovec - iovec + sys_poll - sys_poll + sys_tee - sys_tee + sys_sysinfo - sys_sysinfo + sys_swapon - sys_swapon + swap_info - swap_info + sys_msync - sys_msync + do_mmap - - up - - do_mmap + + up + + mutex_unlock - mutex_unlock + mutex_lock_interruptible - mutex_lock_interruptible + pgd_t - pgd_t + pmd_t - pmd_t + pte_t - pte_t + setup_arch - setup_arch + mm_init - mm_init + kmem_cache_init - kmem_cache_init + vm_stat - vm_stat + sys_capset - sys_capset + x86_init - x86_init + zonelist - zonelist + kfree - kfree + __free_pages - __free_pages + __free_one_page - __free_one_page + security_capset - - handle_sysrq - - - printk - - - log_buf - - - kgdb_breakpoint - - security_capset + + handle_sysrq + + + printk + + + log_buf + + + kgdb_breakpoint + + sys_ptrace - sys_ptrace + oprofile_init - oprofile_init + oprofile_start - oprofile_start + register_kprobe - register_kprobe + kernel_param - kernel_param + native_init_IRQ - native_init_IRQ + set_intr_gate - set_intr_gate + schedule_work - schedule_work + tasklet_action - tasklet_action + softirq_init - softirq_init + module_param - module_param + bus_register - bus_register + mem_init - mem_init + vmalloc_init - vmalloc_init + /sys/class/ - /sys/class/ + kobject_uevent_init - kobject_uevent  - kobject_uevent_init + kobject_uevent  + fsnotify - fsnotify + sys_fanotify_init - sys_fanotify_init + drm_driver - drm_driver + out_of_memory - out_of_memory + vfree - vfree + . - . + . - . + sys_chown - sys_chown + fsnotify_change - fsnotify_change + fanotify_handle_event - fanotify_handle_event + /proc/meminfo - /proc/meminfo + totalram_pages - totalram_pages + num_physpages - - num_physpages + + INIT_WORK - INIT_WORK + queue_work - queue_work + usb_stor_host_template - usb_stor_host_template + scsi_host_alloc - scsi_host_alloc + sys_getdents - sys_getdents + ext4_readdir - ext4_readdir + generic_file_aio_read - generic_file_aio_read + free_list - free_list + free_area - free_area + NR_FREE_PAGES - NR_FREE_PAGES + /proc/net/ - /proc/net/ + tcp4_seq_show - tcp4_seq_show + sg_proc_seq_show_dev - sg_proc_seq_show_dev + rt_cache_seq_show - rt_cache_seq_show + sys_connect - sys_connect + sys_accept - sys_accept + sys_bind - sys_bind + sys_listen - sys_listen + sys_sendmsg - sys_sendmsg + sys_recvmsg - sys_recvmsg + sys_setsockopt - sys_setsockopt + sock_sendpage - sock_sendpage + sock_splice_read - sock_splice_read + sys_sendfile - sys_sendfile + do_splice_direct - do_splice_direct + sys_splice - sys_splice + e1000_xmit_frame - e1000_xmit_frame + e1000_intr - e1000_intr + usbnet_probe - usbnet_probe + netif_carrier_on - netif_carrier_on + ip_route_input - ip_route_input + udp_rcv - udp_rcv + tcp_v4_rcv - tcp_v4_rcv + ip_local_deliver - ip_local_deliver + ip_push_pending_frames - ip_push_pending_frames + functionsimplementations - functionsimplementations + boot, shutdownpower management - boot, shutdownpower management + hibernate - hibernate + machine_ops - machine_ops + early_trap_init - early_trap_init + inet_init - inet_init + udp_sendpage - udp_sendpage + tcp_sendpage - tcp_sendpage + tcp_splice_read - tcp_splice_read + spin_unlock_irqrestore - spin_unlock_irqrestore + spin_lock_irqsave - spin_lock_irqsave + wait_event - wait_event + wait_for_completion - wait_for_completion + - + complete - complete + owner - owner + run_timer_softirq - run_timer_softirq + si_meminfo - si_meminfo + si_swapinfo - si_swapinfo + sys_mincore - - ACPI - - - mm/slub.c - - - mm/slab.c - - + y="286.30713">sys_mincore + + ACPI + + + mm/slub.c + + + mm/slab.c + diff --git a/Linux_kernel_diagram.dot b/Linux_kernel_diagram.dot deleted file mode 100644 index 634ba50..0000000 --- a/Linux_kernel_diagram.dot +++ /dev/null @@ -1,600 +0,0 @@ -digraph matrix { - graph [newrank=true, - nodesep=0.3, - ranksep=0.2, - overlap=true, - splines=false, - ]; - node [fixedsize=false, - fontname=Ubuntu - fontsize=24, - height=1, - shape=box, - style="filled,setlinewidth(5)", - width=2.2 - ]; - edge [arrowhead=none, - arrowsize=0.5, - labelfontname="Ubuntu", - weight=10, - style="filled,setlinewidth(5)" - ]; - { - node [color="#e27dd6ff"]; - system_ [color="#e27dd6ff", - fixedsize=true, - height=0, - shape=point, - style=invis, - shape=point - ]; - system [color="#e27dd6ff", - URL="https://en.wikibooks.org/wiki/The_Linux_Kernel/System", - fillcolor=white, - fixedsize=true, - height=0.6, - row=func, - width=2]; - system -> system_ [arrowhead="", - color="#e27dd6ff", - row=func] - SCI [color="#e27dd6ff", - URL="https://en.wikibooks.org/wiki/The_Linux_Kernel/Syscalls", - fillcolor="#d9e7ee", - fixedsize=true, - label="System calls", - row=usr, - shape=ellipse]; - sysfs [color="#e27dd6ff", - fillcolor="#b2d3e4", - label="proc & sysfs\nfile systems"]; - SCI -> sysfs [color="#e27dd6ff"]; - DM [color="#e27dd6ff", - fillcolor="#91b5c9", - fixedsize=true, - fontsize=20, - height=0.8, - label="Device\nModel", - shape=octagon, - width=2]; - sysfs -> DM [color="#e27dd6ff"]; - log_sys [color="#e27dd6ff", - fillcolor="#6a9ab1", - fontsize=20, - label="system run,\nmodules,\ngeneric\nHW access "]; - DM -> log_sys [color="#e27dd6ff"]; - bus_drv [color="#e27dd6ff", - fillcolor="#71809b", - label="bus drivers"]; - log_sys -> bus_drv [color="#e27dd6ff"]; - H2 [color="#e27dd6ff", - fillcolor="#777777", - fontcolor=white, - fontsize=20, - label="busess:\nPCI, USB ...", - row=chip]; - bus_drv -> H2 [color="#e27dd6ff"]; - } - { - node [color="#61c2c5"]; - edge [color="#61c2c5"]; - networking_ [color="#61c2c5", - fixedsize=true, - height=0, - shape=point, - style=invis, - shape=point - width=0]; - networking [color="#61c2c5", - URL="https://en.wikibooks.org/wiki/The_Linux_Kernel/Networking", - fillcolor=white, - fixedsize=true, - height=0.6, - row=func, - width=2]; - networking -> networking_ [arrowhead="", - color="#61c2c5", - row=func]; - sock [color="#61c2c5", - fillcolor="#d9e7ee", - fixedsize=true, - label=Sockets, - row=usr, - shape=ellipse]; - prot_fam [color="#61c2c5", - fillcolor="#b2d3e4", - label="protocol\nfamilies"]; - sock -> prot_fam [color="#61c2c5"]; - log_prot [color="#61c2c5", - fillcolor="#6a9ab1", - label="protocols:\nTCP, UDP, IP"]; - prot_fam -> log_prot [color="#61c2c5"]; - netif [color="#61c2c5", - fillcolor="#71809b", - fontsize=20, - label="network\ninterfaces\nand drivers"]; - log_prot -> netif [color="#61c2c5"]; - net_hw [color="#61c2c5", - fillcolor="#777777", - fontcolor=white, - fontsize=20, - label="network:\nEthernet, WiFi ...", - row=chip]; - netif -> net_hw [color="#61c2c5"]; - NFS [color="#8383cc", - fillcolor="#91b5c9", - fixedsize=true, - height=0.8, - label=NFS, - shape=octagon, - width=1.2]; - NFS -> log_prot [color="#61c2c5", - weight=0]; - } - { - node [color="#8383cc"]; - edge [color="#8383cc"]; - NFS; - storage_ [color="#8383cc", - shape=point - fixedsize=true, - height=0, - style=invis, - width=0]; - storage [color="#8383cc", - URL="https://en.wikibooks.org/wiki/The_Linux_Kernel/Storage", - fillcolor=white, - fixedsize=true, - height=0.6, - row=func, - width=2]; - storage -> storage_ [arrowhead="", - color="#8383cc", - row=func]; - FS [color="#8383cc", - fillcolor="#d9e7ee", - fixedsize=true, - label="files and\ndirectories", - row=usr, - shape=ellipse]; - VFS [color="#8383cc", - fillcolor="#b2d3e4", - label="Virtual\nFile System"]; - FS -> VFS [color="#8383cc"]; - VFS -> NFS [color="#8383cc", - weight=0]; - logFS [color="#8383cc", - fillcolor="#6a9ab1", - fontsize=20, - label="logical\nfilesystems:\next3, xfs ..."]; - VFS -> logFS [color="#8383cc"]; - PC [color="#51bf5b", - fillcolor="#91b5c9", - fixedsize=true, - fontsize=20, - height=0.8, - label="page\ncache", - shape=octagon, - width=1.2]; - VFS -> PC [color="#8383cc", - weight=0]; - mmap [color="#51bf5b", - fillcolor="#91b5c9", - fixedsize=true, - fontsize=20, - height=0.8, - label="memory\nmapping", - shape=octagon, - width=2]; - VFS -> mmap [color="#8383cc", - weight=0]; - block [color="#8383cc", - fillcolor="#71809b", - fontsize=20, - label="Block\ndevices\nand drivers"]; - logFS -> block [color="#8383cc"]; - PA [color="#51bf5b", - fillcolor="#71809b", - label="Page\nAllocator"]; - PC -> PA [color="#51bf5b", - weight=0]; - H4 [color="#8383cc", - fillcolor="#777777", - fontcolor=white, - fontsize=20, - label="storage devices:\nSCSI, NVMe ...", - row=chip]; - block -> H4 [color="#8383cc"]; - SW [color="#8383cc", - fillcolor="#91b5c9", - fixedsize=true, - label=Swap, - height=0.8, - shape=octagon, - width=1.2]; - SW -> block [color="#8383cc", - weight=0]; - } - { - node [color="#c46747"]; - edge [color="#c46747"]; - processing_ [color="#c46747", - fixedsize=true, - height=0, - shape=point - style=invis, - width=0]; - processing [color="#c46747", - URL="https://en.wikibooks.org/wiki/The_Linux_Kernel/Processing", - fillcolor=white, - fixedsize=true, - height=0.6, - row=func, - width=2]; - processing -> processing_ [arrowhead="", - color="#c46747", - row=func]; - proc [color="#c46747", - fillcolor="#d9e7ee", - fixedsize=true, - label=Processes, - row=usr, - shape=ellipse]; - Tasks [color="#c46747", - fillcolor="#b2d3e4"]; - proc -> Tasks [color="#c46747"]; - sync [color="#c46747", - fillcolor="#91b5c9", - fixedsize=true, - fontsize=20, - fontname="Ubuntu Condensed" - label=synchronization, - height=0.7, - //width=2, - shape=octagon]; - Tasks -> sync [color="#c46747"]; - sched [color="#c46747", - fillcolor="#6a9ab1", - label=Scheduler]; - sync -> sched [color="#c46747"]; - IRQ [color="#c46747", - fillcolor="#71809b", - fontsize=20, - label="interrupts\ncore,\nCPU arch"]; - sched -> IRQ [color="#c46747"]; - CPU [color="#c46747", - fillcolor="#777777", - fontcolor=white, - fontsize=20, - row=chip]; - IRQ -> CPU [color="#c46747"]; - } - { - node [color="#cfbf57ff", - - ]; - edge [color="#cfbf57ff", - weight=10 - ]; - HI_ [color="#cfbf57ff", - fixedsize=true, - height=0, - shape=point - style=invis, - width=0]; - HI [color="#cfbf57ff", - URL="https://en.wikibooks.org/wiki/The_Linux_Kernel", - fillcolor=white, - fixedsize=true, - fontsize=12, - height=0.6, - label="human\ninterface", - row=func, - width=2]; - HI -> HI_ [arrowhead="", - color="#cfbf57ff", - row=func]; - char [color="#cfbf57ff", - fillcolor="#d9e7ee", - fixedsize=true, - label="char\ndevices", - row=usr, - shape=ellipse]; - input [color="#cfbf57ff", - fillcolor="#b2d3e4", - label="input\nsubsystem"]; - char -> input [color="#cfbf57ff"]; - F7 [color="#cfbf57ff", - fillcolor="#6a9ab1", - label="HI class\ndrivers"]; - input -> F7 [color="#cfbf57ff"]; - HID [color="#cfbf57ff", - fillcolor="#71809b", - fontsize=20, - URL="https://www.kernel.org/doc/html/latest/hid/", - label="HI\nperipherals\ndrivers"]; - F7 -> HID [color="#cfbf57ff" - ]; - H7 [color="#cfbf57ff", - fillcolor="#777777", - fontcolor=white, - fontsize=20, - label="display, keyboard,\nmouse, audio", - row=chip]; - HID -> H7 [color="#cfbf57ff" ]; - } - { - graph [rank=same]; - edge [style=invis, - weight=1 - ]; - system; - networking; - system -> networking [weight=1]; - storage; - networking -> storage [weight=1]; - memory [color="#51bf5b", - URL="https://en.wikibooks.org/wiki/The_Linux_Kernel/Memory", - fillcolor=white, - fixedsize=true, - height=0.6, - row=func, - width=2]; - storage -> memory [weight=1]; - processing; - HI; - processing -> HI [weight=1]; - memory -> processing [weight=1]; - functions_ [fixedsize=true, - height=0, - shape=point - style=invis, - width=0]; - functions_ -> system [weight=1]; - functions [color=gray, - tooltip="Columns represent main functionalities of the kernel", - URL="http://www.makelinux.net/ldd3/chp-1-sect-2.shtml", - fillcolor=gray, - fixedsize=true, - height=0.6, - row=func, - style=dashed, - width=1.6]; - functions -> functions_ [arrowhead="", - color=gray, - style="", - weight=""]; - } - { - graph [rank=same]; - SCI; - sock; - FS; - proc; - char; - usr_ [fixedsize=true, - height=0, - shape=point - style=invis, - width=0.5]; - usr [fillcolor="#d9e7eeff", - fixedsize=true, - label="user space\ninterfaces", - row=usr, - shape=ellipse, - style="filled,setlinewidth(0)"]; - MA [color="#51bf5b", - fillcolor="#d9e7ee", - fixedsize=true, - label="memory\naccess", - row=usr, - shape=ellipse]; - } - { - edge [style=invis, - weight=10 - ]; - system_; - SCI; - system_ -> SCI; - networking_; - sock; - networking_ -> sock; - storage_; - FS; - storage_ -> FS; - processing_; - proc; - processing_ -> proc; - HI_; - char; - HI_ -> char; - MA; - memory_ [fixedsize=true, - height=0, - shape=point, - style=invis, - width=0]; - memory_ -> MA; - } - { - graph [rank=same]; - sysfs; - prot_fam; - VFS; - Tasks; - input; - D0 [fixedsize=true, - height=0, - shape=point, - style=invis, - width=0]; - virt [fillcolor="#b2d3e4", - label="virtual\nsubsystems", - URL="https://en.wikipedia.org/wiki/Proxy_pattern", - tooltip="proxy between standard user space interfaces and internal implementations", - style="filled,setlinewidth(0)"]; - VM [color="#51bf5b", - fillcolor="#b2d3e4", - label="Virtual\nmemory"]; - } - { - graph [rank=same]; - DM; - NFS; - mmap; - sync; - E0 [fixedsize=true, - height=0, - shape=point, - style=invis, - width=0]; - bridges [fillcolor="#91b5c9", - shape=octagon, - tooltip="bridges between uniform virtual interfaces and various implementations", - URL="https://en.wikipedia.org/wiki/Bridge_pattern", - style="filled,setlinewidth(0)"]; - } - { - graph [rank=same]; - log_sys; - log_prot; - logFS; - sched; - F7; - F0 [fixedsize=true, - height=0, - shape=point, - style=invis, - width=0]; - logical [fillcolor="#6a9ab1", - style="filled,setlinewidth(0)"]; - log_mem [color="#51bf5b", - fillcolor="#6a9ab1", - label="logical\nmemory"]; - } - { - graph [rank=same]; - bus_drv; - netif; - block; - PA; - IRQ; - HID; - G0 [fixedsize=true, - height=0, - shape=point, - style=invis, - width=0]; - HWI [fillcolor="#71809b", - label="hardware\ninterfaces", - style="filled,setlinewidth(0)"]; - } - { - graph [rank=same]; - H2; - net_hw; - H4; - CPU; - H7; - H0 [fixedsize=true, - height=0, - shape=point, - style=invis, - width=0]; - HW [fillcolor="#777777", - fontcolor=white, - label="electronics,\nhardware", - row=chip, - style="filled,setlinewidth(0)"]; - H5 [color="#51bf5b", - fillcolor="#777777", - fontcolor=white, - fontsize=20, - label="MMU, RAM", - row=chip]; - } - subgraph mem { - node [color="#51bf5b", - height=0.5 - ]; - edge [color="#51bf5b"]; - PC; - mmap; - SW; - mmap -> SW [color="#51bf5b", - weight=0]; - log_mem; - mmap -> log_mem [color="#51bf5b"]; - PA; - H5; - PA -> H5 [color="#51bf5b"]; - memory; - memory_; - memory -> memory_ [arrowhead="", - color="#51bf5b", - row=func]; - MA; - VM; - MA -> VM [color="#51bf5b"]; - VM -> mmap [color="#51bf5b"]; - log_mem -> PA [color="#51bf5b"]; - } - bottom [label="© 2007-2020 Constantine Shulyupin http://www.MakeLinux.net/kernel/diagram", - shape=plaintext, - style=""]; - H4 -> bottom [style=invis]; - layers [fillcolor=lightgray, - tooltip="Functionalities are divided to common layers. It is approximate division.", - height=0.1, - style="filled,setlinewidth(0)", - width=0.5]; - functions -> layers [ style=invis ]; - usr -> usr_ [arrowhead="", - color="#d9e7eeff", - minlen=2]; - usr -> virt [color="#d9e7eeff"]; - virt -> D0 [arrowhead="", - color="#b2d3e4", - minlen=2]; - virt -> bridges [color="#b2d3e4"]; - bridges -> E0 [arrowhead="", - color="#91b5c9", - minlen=2, - style="filled,setlinewidth(6)", - weight=""]; - bridges -> logical [color="#91b5c9", - style="filled,setlinewidth(6)"]; - logical -> F0 [arrowhead="", - color="#6a9ab1", - minlen=2, - row=logical, - style="filled,setlinewidth(6)", - weight=""]; - logical -> HWI [color="#6a9ab1", - row=logical, - style="filled,setlinewidth(6)"]; - HWI -> G0 [arrowhead="", - color="#71809b", - minlen=2, - row=HWI, - style="filled,setlinewidth(6)", - weight=""]; - HWI -> HW [color="#71809b", - row=HWI, - style="filled,setlinewidth(6)"]; - HW -> H0 [arrowhead="", - color="#777777", - minlen=2, - row=chip, - style="filled,setlinewidth(6)", - weight=""]; - layers -> usr [arrowhead="", - color=gray, - style="filled,setlinewidth(1)"]; - LKD [fontsize=40, - label="Linux kernel diagram", - shape=plain, - style=""]; - LKD -> storage [style=invis]; -} diff --git a/srcxray.py b/srcxray.py index fdf3bc8..76728eb 100755 --- a/srcxray.py +++ b/srcxray.py @@ -4,27 +4,23 @@ # # Analyzes interconnections between functions and structures in source code. # -# Uses doxygen, git grep --show-functionm and cscope to +# Uses cscope and git grep --show-function to # reveal references between identifiers. # -# Since 2018, Costa Shulyupin, costa@MakeLinux.net +# 2018 Constantine Shulyupin, const@MakeLinux.com # import inspect -from inspect import (currentframe, getframeinfo, getouterframes, stack, - getmembers, isfunction) -import types import random import os import sys -from sys import * import collections from munch import * -from subprocess import * +import subprocess import re import networkx as nx # from networkx.drawing.nx_agraph import read_dot # changes order of successors -# from networkx.drawing.nx_pydot import read_dot # no bad +from networkx.drawing.nx_pydot import read_dot from networkx.generators.ego import * from networkx.algorithms.dag import * from networkx.utils import open_file, make_str @@ -32,15 +28,12 @@ import difflib import glob from pathlib import * -import pygraphviz # python3-pygraphviz +import pygraphviz import unittest import types -from xml.dom.minidom import parse -import xml.dom.minidom -import ast default_root = 'starts' -ignores = ('aligned unlikely typeof u32 ' +black_list = ('aligned __attribute__ unlikely typeof u32 ' 'PVOP_CALLEE0 PVOP_VCALLEE0 PVOP_VCALLEE1 if trace_hardirqs_off ' 'i NULL likely unlikely true false test_bit NAPI_GRO_CB clear_bit ' 'atomic_read preempt_disable preempt_enable container_of ENOSYS ' @@ -50,7 +43,7 @@ 'list_empty memcpy size_t loff_t pos d_inode dput copy_to_user EIO bool out IS_ERR ' 'EPERM rcu_read_lock rcu_read_unlock spin_lock spin_unlock list_for_each_entry kfree ' 'GFP_KERNEL ENOMEM EFAULT ENOENT EAGAIN PTR_ERR PAGE_SHIFT PAGE_SIZE ' - 'pgoff_t pte_t pmd_t HPAGE_PMD_NR PageLocked entry swp_entry_t next unlock_page spinlock_t end XXstart ' + 'pgoff_t pte_t pmd_t HPAGE_PMD_NR PageLocked entry swp_entry_t next unlock_page spinlock_t end start ' ' VM_BUG_ON VM_BUG_ON_PAGE BDI_SHOW max ' 'ssize_t path_put __user ' 'list_del compound_head list_add cond_resched put_page nr_pages min spin_lock_irqsave IS_ENABLED ' @@ -66,18 +59,16 @@ 'retry LOOKUP_REVAL retry_estale user_path_at lookup_flags old ' 'current_user_ns spin_lock_irq spin_unlock_irq prepare_creds ' 'tasklist_lock commit_creds read_lock read_unlock SIGKILL SIGSTOP abort_creds fd_install ' - 'real_mount FMODE_WRITE tv_nsec putname ' + 'real_mount FMODE_WRITE tv_nsec putname ,' ).split() -level_limit = 10 -limit = 1000 +level_limit = 8 +limit = 100000 n = 0 -cflow_structs = False + scaled = False -verbose = False -files = collections.defaultdict(list) def print_limited(a, out=None): out = out if out else sys.stdout @@ -91,72 +82,51 @@ def print_limited(a, out=None): def log(*args, **kwargs): - if not verbose: - return s = str(*args).rstrip() - frameinfo = getframeinfo(currentframe().f_back) - print("%s:%d %s" % (frameinfo.filename, frameinfo.lineno, stack()[1][3]), + print(inspect.stack()[1][3], s, file=sys.stderr, **kwargs) return s def popen(p): - log(p) - return check_output(p, shell=True).decode('utf-8').splitlines() + return subprocess.check_output(p, shell=True).decode('utf-8').splitlines() -def extract_referrer(line): +def extract_referer(line): line = re.sub(r'__ro_after_init', '', line) line = re.sub(r'FNAME\((\w+)\)', r'\1', line) line = re.sub(r'.*TRACE_EVENT.*', '', line) - file_num = r'(^[^\s]+)=(\d+)=[^,]*' - # file=(*name) - m = re.match(file_num + r'\(\*(\b\w+)\)\s*[\(\[=][^;]*$', line) + m = re.match(r'^[^\s]+=[^,]*\(\*(\b\w+)\)\s*[\(\[=][^;]*$', line) if not m: - m = re.match(file_num + r'(\b\w+)\s*[\(\[=][^;]*$', line) - if not m: - m = re.match(file_num + r'struct (\b\w+)', line) + m = re.match(r'^[^\s]+=[^,]*(\b\w+)\s*[\(\[=][^;]*$', line) if m: - return m.groups() + return m.group(1) -def extract_referrer_test(): - passed = 0 +def extract_referer_test(): for a in { - "f=1=good2()", - "f=2=static int fastop(struct x86_emulate_ctxt *ctxt, " + "fs=good2()", + "f=static int fastop(struct x86_emulate_ctxt *ctxt, " + "void (*fop)(struct fastop *))", - "f=3=int good(a, bad (*func)(arg))", - "f=4=EXPORT_SYMBOL_GPL(bad);", - "f=5=bad (*good)()", - "f=6=int FNAME(good)(a)", - "f=7=TRACE_EVENT(bad)", - "f:8: a=in bad()", - "f=9=struct good", - }: - r = extract_referrer(a) - #print(a, '->', r) - if 'bad' in a and r and 'bad' in r[2]: - print("ERROR: ", a, '->', r) - elif 'good' in a and not r: - print("ERROR:", a) - else: - passed += 1 - log(passed) + "f=int good(a, bad (*func)(arg))", + "f=EXPORT_SYMBOL_GPL(bad);", + "f=bad (*good)()", + "f=int FNAME(good)(a)", + "f=TRACE_EVENT(a)", + "f: a=in bad()"}: + print(a, '->', extract_referer(a)) -def func_referrers_git_grep(name): +def func_referers_git_grep(name): res = list() r = None - for line in popen(r'git grep --threads 1 --no-index --word-regexp ' - r'--show-function --line-number ' + for line in popen(r'git grep --threads 1 --no-index --word-regexp --show-function ' r'"^\s.*\b%s" ' r'**.\[hc\] **.cpp **.cc **.hh || true' % (name)): # Filter out names in comment afer function, # when comment start from ' *' # To see the problem try "git grep -p and" for p in { - # exludes: r'.*:\s+\* .*%s', r'.*/\*.*%s', r'.*//.*%s', @@ -164,63 +134,46 @@ def func_referrers_git_grep(name): if re.match(p % (name), line): r = None break - if r and r[2] != name and r[2] not in ignores: + if r and r != name and r not in black_list: res.append(r) r = None - r = extract_referrer(line) - # r is list of file line func - if verbose and r: - print("%-40s\t%s"%(("%s:%s"%(r[0],r[1])),r[2])) + r = extract_referer(line) return res cscope_warned = False -def func_referrers_cscope(name): +def func_referers_cscope(name): global cscope_warned if not os.path.isfile('cscope.out'): if not cscope_warned: - print("Recommended: cscope -Rcbk", file=sys.stderr) + print("Recommended: cscope -bkR", file=sys.stderr) cscope_warned = True return [] - res = list() - r = None - for l in popen(r'cscope -d -L3 "%s"' % (name)): - log(l) - m = re.match(r'([^ ]*) ([^ ]*) ([^ ]*) (.*)', l) - file, func, line_num, line_str = m.groups() - if func in ignores: continue - res.append([file, line_num, func]) - if not res and len(name) > 3: - log(name) - res = func_referrers_git_grep(name) - log(res) + res = list(dict.fromkeys([l.split()[1] for l in popen(r'cscope -d -L3 "%s"' % + (name)) if l not in black_list])) + if not res: + res = func_referers_git_grep(name) return res -def func_referrers_all(name): - return list(dict.fromkeys(func_referrers_git_grep(name) + func_referrers_cscope(name))) +def func_referers_all(name): + return list(dict.fromkeys(func_referers_git_grep(name) + func_referers_cscope(name))) -def referrers_tree(name, referrer=None, printed=None, level=0): - ''' - Arg: - Ex: nfs_root_data - ''' - if not referrer: +def referers_tree(name, referer=None, printed=None, level=0): + if not referer: if os.path.isfile('cscope.out'): - referrer = func_referrers_cscope + referer = func_referers_cscope else: - print("Using git grep only, recommended to run: cscope -Rcbk", - file=sys.stderr) - referrer = func_referrers_git_grep - if isinstance(referrer, str): - referrer = eval(referrer) + print("Using git grep only, recommended to run: cscope -bkR", + file=sys.stderr) + referer = func_referers_git_grep + if isinstance(referer, str): + referer = eval(referer) if not printed: printed = set() - # definition - # cscope -d -L1 "arv_camera_new" if name in printed: print_limited(level*'\t' + name + ' ^') return @@ -230,56 +183,45 @@ def referrers_tree(name, referrer=None, printed=None, level=0): if level > level_limit - 2: print_limited((level + 1)*'\t' + '...') return '' - for a in referrer(name): - name = a[2] - referrers_tree(name, referrer, printed, level + 1) - -def referrers(name): - ''' - Arg: - Ex: nfs_root_data - ''' - #for a in func_referrers_git_grep(name): - # print("%s:%s: %s"%(a[0],a[1],a[2])) - print(' '.join([a[2] for a in func_referrers_git_grep(name)])) + listed = set() + for a in referer(name): + referers_tree(a, referer, printed, level + 1) + listed.add(a) + return '' -def referrers_dep(name, referrer=None, printed=None, level=0): - # Arg: - if not referrer: +def referers_dep(name, referer=None, printed=None, level=0): + if not referer: if os.path.isfile('cscope.out'): - referrer = func_referrers_cscope + referer = func_referers_cscope else: - print("Using git grep only, recommended to run: cscope -Rcbk", + print("Using git grep only, recommended to run: cscope -bkR", file=sys.stderr) - referrer = func_referrers_git_grep - if isinstance(referrer, str): - referrer = eval(referrer) + referer = func_referers_git_grep + if isinstance(referer, str): + referer = eval(referer) if not printed: printed = set() if name in printed: return if level > level_limit - 2: return '' - referrers = [a[2] for a in referrer(name)] - if referrers: + referers = referer(name) + if referers: printed.add(name) - print("%s:" % (name), ' '.join(referrers)) - for a in referrers: - referrers_dep(a, referrer, printed, level + 1) + print("%s:" % (name), ' '.join(referers)) + for a in referers: + referers_dep(a, referer, printed, level + 1) else: pass # TODO: print terminal # print('...') + return '' def call_tree(node, printed=None, level=0): - ''' - Arg: - Ex: start_kernel - ''' if not os.path.isfile('cscope.out'): - print("Please run: cscope -Rcbk", file=sys.stderr) + print("Please run: cscope -bkR", file=sys.stderr) return False if printed is None: printed = set() @@ -295,18 +237,19 @@ def call_tree(node, printed=None, level=0): local_printed = set() for line in popen('cscope -d -L2 "%s"' % (node)): a = line.split()[1] - if a in local_printed or a in ignores: + if a in local_printed or a in black_list: continue local_printed.add(a) # try: call_tree(line.split()[1], printed, level + 1) # except Exception: # pass + return '' def call_dep(node, printed=None, level=0): if not os.path.isfile('cscope.out'): - print("Please run: cscope -Rcbk", file=sys.stderr) + print("Please run: cscope -bkR", file=sys.stderr) return False if printed is None: printed = set() @@ -315,7 +258,7 @@ def call_dep(node, printed=None, level=0): calls = list() for a in [line.split()[1] for line in popen('cscope -d -L2 "%s"' % (node))]: - if a in ignores: + if a in black_list: continue calls.append(a) if calls: @@ -328,6 +271,7 @@ def call_dep(node, printed=None, level=0): pass # TODO: print terminal # print('...') + return '' def my_graph(name=None): @@ -338,14 +282,10 @@ def my_graph(name=None): def reduce_graph(g, m=None): - ''' - Arg: [min in_degree]- removes leaves - Ex2: \"write_dot(reduce_graph(read_dot('doxygen.dot')),'reduced.dot')\" - ''' rm = set() - m = g.number_of_nodes() + 1 if not m else m - log(g.number_of_edges()) - rm = [n for (n, d) in g.out_degree if not d and g.in_degree(n) < m] + m = g.number_of_nodes() if not m else m + print(g.number_of_edges()) + rm = [n for (n, d) in g.out_degree if not d and g.in_degree(n) <= m] g.remove_nodes_from(rm) print(g.number_of_edges()) return g @@ -404,8 +344,7 @@ def syscalls(): if not os.path.isfile(scd): os.system("grep SYSCALL_DEFINE -r --include='*.c' > " + scd) with open(scd, 'r') as f: - v = set(['sigsuspend', 'llseek', 'sysfs', - 'sync_file_range2', 'ustat', 'bdflush']) + v = set(['sigsuspend', 'llseek', 'sysfs', 'sync_file_range2', 'ustat', 'bdflush']) for s in f: if any(x in s.lower() for x in ['compat', 'stub']): continue @@ -417,7 +356,7 @@ def syscalls(): r'.*64', r'.*32$', r'.*16$', - }: + }: if re.match(p, m.group(2)): m = None break @@ -455,24 +394,31 @@ def syscalls(): # write_dot to_agraph AGraph # agwrite # srcxray.py 'write_dot(syscalls(), "syscalls.dot")' +# srcxray.py "write_dot(import_cflow(), 'a.dot')" # write_graphml +# F=sys_mount; srcxray.py "digraph_print(import_cflow(), ['$F'])" > $F.tree +# srcxray.py "leaves(read_dot('a.dot'))" # srcxray.py "most_used(read_dot('a.dot'))" # srcxray.py "digraph_print(read_dot('a.dot'))" # srcxray.py "write_dot(reduce_graph(read_dot('no-loops.dot')),'reduced.dot')" -# a=sys_clone;srcxray.py "write_dot(rank_couples(reduce_graph(remove_loops(read_dot('$a.dot')))),'$a.dot')" # srcxray.py "pprint(most_used(read_dot('a.dot')))" +# srcxray.py "write_dot(digraph_tree(read_dot2('all.dot'), ['sys_clone']), 'sys_clone.dot')" # srcxray.py "write_dot(add_rank('reduced.dot'), 'ranked.dot')" -# srcxray.py "write_dot(remove_loops(read_dot('reduced.dot')), 'no-loops.dot')" +# srcxray.py "write_dot(remove_loops(read_dot2('reduced.dot')), 'no-loops.dot')" def cleanup(a): - log('') g = to_dg(a) print(dg.number_of_edges()) - dg.remove_nodes_from(ignores) + dg.remove_nodes_from(black_list) print(dg.number_of_edges()) write_dot(dg, a) +def leaves(dg): + # [x for x in G.nodes() if G.out_degree(x)==0 and G.in_degree(x)==1] + return {n: dg.in_degree(n) for (n, d) in dg.out_degree if not d} + + def sort_dict(d): return [a for a, b in sorted(d.items(), key=lambda k: k[1], reverse=True)] @@ -488,47 +434,14 @@ def most_used(dg, ins=10, outs=10): def starts(dg): # roots return {n: dg.out_degree(n) for (n, d) in dg.in_degree if not d} -def exclude(i, excludes=[], ignores=ignores): - if i in ignores: - return True - for e in excludes: - if re.match(e, i): - return True -def digraph_predecessors(dg, starts, levels = 100, excludes = [], ignores=ignores): - dg = to_dg(dg) - passed = set() - # for i in [_ for _ in dg.predecessors(start)]: - p = nx.DiGraph() - for e in excludes: - log(e) - while levels: - #log(levels) - #log(starts) - s2 = starts - starts = set() - for s in s2: - for i in dg.predecessors(s): - if i in passed or exclude(i, excludes, ignores): - continue - passed.add(i) - starts.add(i) - p.add_edge(i, s) - levels-=1 - return p - - -def digraph_tree(dg, starts=None, ignores=ignores): - ''' - Arg: - extract a subgraph from a graph - Ex2: \"write_dot(digraph_tree(read_dot('doxygen.dot'), ['main']), 'main.dot')\" - ''' +def digraph_tree(dg, starts=None, black_list=black_list): tree = nx.DiGraph() def sub(node): tree.add_node(node) for o in dg.successors(node): - if o in ignores or tree.has_edge(node, o) or o in starts: + if o in black_list or tree.has_edge(node, o) or o in starts: # print(o) continue tree.add_edge(node, o) @@ -539,43 +452,35 @@ def sub(node): starts = {} for i in [n for (n, d) in dg.in_degree if not d]: starts[i] = dg.out_degree(i) - starts = [a[0] for a in sorted( - starts.items(), key=lambda k: k[1], reverse=True)] + starts = [a[0] for a in sorted(starts.items(), key=lambda k: k[1], reverse=True)] if len(starts) == 1: sub(starts[0]) elif len(starts) > 1: for o in starts: - if o in ignores: + if o in black_list: continue sub(o) return tree def digraph_print(dg, starts=None, dst_fn=None, sort=False): - ''' - Arg: - print graphs as text tree - ''' dst = open(dst_fn, 'w') if dst_fn else None - printed = set() - def digraph_print_sub(path='', node=None, level=0): - if node in ignores: + def digraph_print_sub(path='', node=None, printed=None, level=0): + if node in black_list: return if node in printed: print_limited(level*'\t' + str(node) + ' ^', dst) return outs = {_: dg.out_degree(_) for _ in dg.successors(node)} if sort: - outs = {a: b for a, b in sorted( - outs.items(), key=lambda k: k[1], reverse=True)} + outs = {a: b for a, b in sorted(outs.items(), key=lambda k: k[1], reverse=True)} s = '' if 'rank' in dg.nodes[node]: s = str(dg.nodes[node]['rank']) ranks[dg.nodes[node]['rank']].append(node) if outs: - s += ' ...' if level > level_limit - 2 else '' - else: - s+=' @' + path + s += ' ...' if level > level_limit - 2 else ' @' + path print_limited(level*'\t' + str(node) + s, dst) printed.add(node) if level > level_limit - 2: @@ -585,14 +490,14 @@ def digraph_print_sub(path='', node=None, level=0): if o in passed: continue passed.add(o) - digraph_print_sub(path + ' ' + str(node), o, level + 1) + digraph_print_sub(path + ' ' + str(node), o, printed, level + 1) + printed = set() if not starts: starts = {} for i in [n for (n, d) in dg.in_degree if not d]: starts[i] = dg.out_degree(i) - starts = [a[0] for a in sorted( - starts.items(), key=lambda k: k[1], reverse=True)] + starts = [a[0] for a in sorted(starts.items(), key=lambda k: k[1], reverse=True)] if len(starts) > 1: print_limited(default_root, dst) for s in starts: @@ -603,66 +508,59 @@ def digraph_print_sub(path='', node=None, level=0): continue passed.add(o) if o in dg: - digraph_print_sub('', o) - # not yet printed rest: - for o in dg.nodes(): - if o not in printed: - digraph_print_sub('', o) + for o in dg.nodes(): + if o not in printed: + digraph_print_sub('', o, printed) if dst_fn: print(dst_fn) dst.close() def cflow_preprocess(a): - with open(a, 'rb') as f: + with open(a, 'r') as f: for s in f: - try: - s = s.decode('utf-8') - except UnicodeDecodeError: - s = s.decode('latin1') - if cflow_structs: - # treat structs like functions - s = re.sub(r"^static struct (\w+) = ", r"\1()", s) - s = re.sub(r"^static struct (\w+)\[\] = ", r"\1()", s) - s = re.sub(r"^static const struct (\w+)\[\] = ", r"\1()", s) - s = re.sub(r"^struct (.*) =", r"\1()", s) + # treat struct like function + s = re.sub(r"^static struct (.*) = ", r"\1()", s) + s = re.sub(r"^static struct (.*)\[\] = ", r"\1()", s) + s = re.sub(r"^static const struct (.*)\[\] = ", r"\1()", s) s = re.sub(r"^static __initdata int \(\*actions\[\]\)\(void\) = ", - "int actions()", s) # init/initramfs.c + "int actions()", s) # treat struct like function s = re.sub(r"^static ", "", s) - s = re.sub(r"SENSOR_DEVICE_ATTR.*\((\w*),", - r"void sensor_dev_attr_\1()(", s) + s = re.sub(r"SENSOR_DEVICE_ATTR.*\((\w*),", r"void sensor_dev_attr_\1()(", s) s = re.sub(r"COMPAT_SYSCALL_DEFINE[0-9]\((\w*),", r"compat_sys_\1(", s) - s = re.sub(r"SYSCALL_DEFINE[0-9]\((\w*)", r"sys_\1(", s) + s = re.sub(r"SYSCALL_DEFINE[0-9]\((\w*),", r"sys_\1(", s) s = re.sub(r"__setup\(.*,(.*)\)", r"void __setup() {\1();}", s) s = re.sub(r"^(\w*)param\(.*,(.*)\)", r"void \1param() {\2();}", s) s = re.sub(r"^(\w*)initcall\((.*)\)", r"void \1initcall() {\2();}", s) s = re.sub(r"^static ", "", s) + # s = re.sub(r"__read_mostly", "", s) s = re.sub(r"^inline ", "", s) s = re.sub(r"^const ", "", s) + s = re.sub(r"^struct (.*) =", r"\1()", s) + s = re.sub(r"^struct ", "", s) s = re.sub(r"\b__initdata\b", "", s) - s = re.sub(r"DEFINE_PER_CPU\((.*),(.*)\)", r"\1 \2", s) - s = re.sub(r"^(\w+) {$", r"void \1() {", s) + # s = re.sub(r"__init_or_module", "", s) + # __attribute__ # for line in sys.stdin: sys.stdout.write(s) cflow_param = { - "modifier": "__init __inline__ noinline __initdata __randomize_layout asmlinkage " - " __visible __init __leaf__ __ref __latent_entropy __init_or_module libmosq_EXPORT", + "modifier": "__init __inline__ noinline __initdata __randomize_layout asmlinkage " + " __visible __init __leaf__ __ref __latent_entropy __init_or_module ", "wrapper": "__attribute__ __section__ " "TRACE_EVENT MODULE_AUTHOR MODULE_DESCRIPTION MODULE_LICENSE MODULE_LICENSE MODULE_SOFTDEP " - "INIT_THREAD_INFO " "__acquires __releases __ATTR" # "wrapper": "__setup early_param" -} + } # export CPATH=:include:arch/x86/include:../build/include/:../build/arch/x86/include/generated/:include/uapi # srcxray.py "'\n'.join(cflow('init/main.c'))" -def cflow(a=None): +def cflow(a): if os.path.isfile('include/linux/cache.h'): for m in popen("ctags -x --c-kinds=d include/linux/cache.h | cut -d' ' -f 1 | sort -u"): if m in cflow_param['modifier']: @@ -670,31 +568,29 @@ def cflow(a=None): else: cflow_param['modifier'] += ' ' + a if not a: - a = "$(cat cscope.files)" if os.path.isfile( - 'cscope.files') else "*.c *.h *.cpp *.hh " + # arg = "$(find -name '*.[ch]' -o -name '*.cpp' -o -name '*.hh')" + a = "$(cat cscope.files)" if os.path.isfile('cscope.files') else "*.c *.h *.cpp *.hh " elif isinstance(a, list): pass elif os.path.isdir(a): - a = "$(find {0} -name '*.[ch]' -o -name '*.cpp' -o -name '*.hh')".format(a) pass elif os.path.isfile(a): pass # "--depth=%d " %(level_limit+1) + # --debug=1 - cflow = (r"cflow -m _ignore_main_get_all_ -v " + cflow = (r"cflow -v " # + "-DCONFIG_KALLSYMSZ " + "--preprocess='srcxray.py cflow_preprocess' " + ''.join([''.join(["--symbol={0}:{1} ".format(w, p) - for w in cflow_param[p].split()]) - for p in cflow_param.keys()]) + for w in cflow_param[p].split()]) + for p in cflow_param.keys()]) + " --include=_sxt --brief --level-indent='0=\t' " + a) - log(cflow) + # print(cflow) return popen(cflow) def import_cflow(a=None, cflow_out=None): - # Arg: $none_or_dir_or_file_or_mask cf = my_graph() stack = list() nprev = -1 @@ -713,7 +609,7 @@ def import_cflow(a=None, cflow_out=None): if n <= nprev: stack = stack[:n - nprev - 1] # print(n, id, stack) - if id not in ignores: + if id not in black_list: if len(stack): cf.add_edge(stack[-1], id) stack.append(id) @@ -721,40 +617,8 @@ def import_cflow(a=None, cflow_out=None): return cf -def import_outline(a=None): - ''' - Arg: - convert tree text to graph - Ex2: \"write_dot(import_outline('outline.txt'),'outline.dot')\" - ''' - cf = my_graph() - stack = list() - nprev = -1 - with open(a, 'r') as f: - for line in f: - m = re.match(r'^([\t ]*)(.*)', str(line)) - if m: - n = len(m.group(1)) - id = str(m.group(2)) - else: - raise Exception(line) - if not id: - continue - id = re.sub(' \^$', '', id) - if n <= nprev: - stack = stack[:n - nprev - 1] - # print(n, id, stack) - if id not in ignores: - if len(stack): - cf.add_edge(stack[-1], id) - stack.append(id) - nprev = n - return cf - - def rank(g, n): try: - if g.nodes[n]['rank1'] == g.nodes[n]['rank2']: - return g.nodes[n]['rank1'] if g.nodes[n]['rank1'] < abs(g.nodes[n]['rank2']): return g.nodes[n]['rank1'] else: @@ -763,15 +627,7 @@ def rank(g, n): return None -def esc(s): - # re.escape(n)) - return s - - def write_dot(g, dot): - ''' - Arg: - writes a graph into a file with custom attributes - ''' dot = str(dot) dot = open(dot, 'w') dot.write('strict digraph "None" {\n') @@ -780,7 +636,7 @@ def write_dot(g, dot): dot.write('node [fontname=Ubuntu,shape=none];\n') # dot.write('edge [width=10000];\n') dot.write('edge [width=1];\n') - g.remove_nodes_from(ignores) + g.remove_nodes_from(black_list) ranks = collections.defaultdict(list) for n in g.nodes(): r = rank(g, n) @@ -788,34 +644,22 @@ def write_dot(g, dot): ranks[r].append(n) if not g.out_degree(n): continue - dot.write('"%s" -> { ' % esc(n)) - dot.write(' '.join(['"%s"' % (esc(str(a))) - for a in g.successors(n)])) - if scaled and r and int(r): + dot.write('"%s" -> { ' % (n)) + dot.write(' '.join(['"%s"' % (str(a)) for a in g.successors(n)])) + if r and scaled: dot.write(' } [penwidth=%d label=%d];\n' % (100/r, r)) else: dot.write(' } ;\n') - # pred - dot.write('// "%s" <- { ' % esc(n)) - dot.write(' '.join(['"%s"' % (esc(str(a))) - for a in g.predecessors(n)])) - dot.write(' } ;\n') print(ranks.keys()) for r in ranks.keys(): - dot.write("{ rank=same %s }\n" % - (' '.join(['"%s"' % (str(a)) for a in ranks[r]]))) + dot.write("{ rank=same %s }\n" % (' '.join(['"%s"' % (str(a)) for a in ranks[r]]))) for n in g.nodes(): - prop = Munch(g.node[n]) + prop = Munch() if scaled and len(ranks): prop.fontsize = 500 + 10000 / (len(ranks[rank(g, n)]) + 1) - prop.fontsize = 30 + min(5 * len(g.edges(n)), 50) - # prop.label = n + ' ' + str(rank(g,n)) if prop: - dot.write('"%s" [%s]\n' % (esc(n), ','.join( - ['%s="%s"' % (a, str(prop[a])) for a in prop]))) - elif not g.number_of_edges(): - dot.write('"%s"\n' % (n)) + dot.write('"%s" [%s]\n' % (n, ','.join(['%s="%s"' % (a, str(prop[a])) for a in prop]))) # else: # dot.write('"%s"\n'%(n)) dot.write('}\n') @@ -824,7 +668,7 @@ def write_dot(g, dot): @open_file(0, mode='r') -def read_dot(dot): +def read_dot2(dot): # read_dot pydot.graph_from_dot_data parse_dot_data from_pydot dg = nx.DiGraph() for a in dot: @@ -832,8 +676,7 @@ def read_dot(dot): if '->' in a: m = re.match('"?([^"]+)"? -> {(.+)}', a) if m: - dg.add_edges_from([(m.group(1), b.strip('"')) - for b in m.group(2).split() if b != m.group(1)]) + dg.add_edges_from([(m.group(1), b.strip('"')) for b in m.group(2).split() if b != m.group(1)]) else: m = re.match('"?([^"]+)"? -> "?([^"]*)"?;', a) if m: @@ -841,24 +684,14 @@ def read_dot(dot): dg.add_edge(m.group(1), m.group(2)) else: log(a) - elif re.match('.*[=\[\]{}]', a): - continue - else: - m = re.match('"?([^"]+)"?', a) - if m: - if m.group(1): - dg.add_node(m.group(1)) return dg def to_dg(a): if isinstance(a, nx.DiGraph): - log(a) return a if os.path.isfile(a): - log(a) - return read_dot(a) - raise(Exception(a)) + return read_dot2(a) def remove_loops(dg): @@ -885,49 +718,15 @@ def remove_loops(dg): return dg -def remove_couples(dg): - couples = [] - for n in dg: - if dg.out_degree(n) == 1: - s = list(dg.successors(n))[0] - if dg.in_degree(s) == 1: - couples.append((n, s)) - pprint(couples) - dg.remove_edges_from(couples) - return dg - - -def rank_couples(dg): - couples = [] - ranked = set() - for n in dg: - if n in ranked: - continue - m = n - while True: - if dg.out_degree(m) == 1: - s = list(dg.successors(m))[0] - if dg.in_degree(s) == 1: - couples.append((m, s)) - ranked.update(set((m, s))) - dg.nodes[m]['rank1'] = dg.nodes[m]['rank2'] = dg.nodes[s]['rank1'] = dg.nodes[s]['rank2'] = n - m = s - continue - break - return dg - - def cflow_dir(a): index = nx.DiGraph() for c in glob.glob(os.path.join(a, "*.c")): g = None dot = str(Path(c).with_suffix(".dot")) if not os.path.isfile(dot): - # c -> cflow and dot g = import_cflow(c, Path(c).with_suffix(".cflow")) write_dot(g, dot) - print(dot, popen("ctags -x %s | wc -l" % (c)) - [0], len(set(e[0] for e in g.edges()))) + print(dot, popen("ctags -x %s | wc -l" % (c))[0], len(set(e[0] for e in g.edges()))) else: print(dot) try: @@ -945,7 +744,6 @@ def cflow_dir(a): def cflow_linux(): - # Arg: dirs = ('init kernel kernel/time ' 'fs fs/ext4 block ' 'ipc net ' @@ -955,17 +753,14 @@ def cflow_linux(): # dirs += ('mm net/ipv4 crypto').split() dirs = ('init kernel arch/x86/kernel fs ').split() - dirs += ['mm'] # fs/notify/fanotify fs/notify/inotify - all = None + try: print('loading all.dot') - all = read_dot('all.dot') + all = read_dot2('all.dot') # all = nx.DiGraph(read_dot('all.dot')) except FileNotFoundError: - pass - if not all: all = nx.DiGraph() for a in dirs: print(a) @@ -982,21 +777,16 @@ def cflow_linux(): start_kernel = digraph_tree(all, ['start_kernel']) write_dot(start_kernel, 'start_kernel.dot') write_dot(reduce_graph(start_kernel), 'start_kernel-reduced.dot') - write_dot(reduce_graph(reduce_graph(start_kernel)), - 'start_kernel-reduced2.dot') - write_dot(reduce_graph(digraph_tree(all, ['sys_clone'])), 'sys_clone.dot') + write_dot(reduce_graph(reduce_graph(start_kernel)), 'start_kernel-reduced2.dot') def stats(a): - ''' - Arg: - measures various simple statistical metrics of a graph - ''' dg = to_dg(a) stat = Munch() im = dict() om = dict() leaves = set() - roots = dict() + roots = set() stat.edge_nodes = 0 stat.couples = 0 for n in dg: @@ -1007,7 +797,7 @@ def stats(a): if id: im[n] = id else: - roots[n] = od + roots.add(n) if od: om[n] = od else: @@ -1018,14 +808,13 @@ def stats(a): stat.max_out_degree = max(dict(dg.out_degree).values()) stat.leaves = len(leaves) stat.roots = len(roots) - stat.big_roots = ' '.join(sort_dict(roots)[:20]) # pprint(im) # pprint(om) stat._popular = ' '.join(sort_dict(im)[:10]) stat._biggest = ' '.join(sort_dict(om)[:10]) gd = remove_loops(dg) stat.dag_longest_path_len = len(dag_longest_path(dg)) - stat.__longest_path = ' '.join(dag_longest_path(dg)[:10] + ['']) + print(' '.join(dag_longest_path(dg))) for a in [nx.DiGraph.number_of_nodes, nx.DiGraph.number_of_edges, nx.DiGraph.number_of_selfloops, nx.DiGraph.order]: stat[a.__name__] = a(dg) @@ -1035,15 +824,12 @@ def stats(a): def dot_expand(a, b): a = to_dg(a) b = to_dg(b) - c = my_graph() - log(a.nodes()) - c.add_edges_from(b.out_edges(b.nbunch_iter(a.nodes()))) - print(list(b.nbunch_iter(a.nodes()))) - return c + a.add_edges_from(list(b.out_edges(b.nbunch_iter(a.nodes())))) + return a def add_rank(g): - g = to_dg(g) + g= to_dg(g) passed1 = set() passed2 = set() rn1 = 1 @@ -1073,218 +859,64 @@ def add_rank(g): return g -def import_symbols(): - sym = my_graph('symbols') - for l in popen('(shopt -s globstar; nm -D -C -A **/*.so.*)'): - q = l.split(maxsplit=2) - m = re.match(r'.*lib(.+).so.*:.*', q[0]) - if not m: - log(q[0]) - continue - if q[1] == 'U': - sym.add_edge(m.group(1), q[2]) - elif q[1] == 'T': - sym.add_edge(q[2], m.group(1)) - print(m.group(1), q[1], q[2]) - return sym - - me = os.path.basename(sys.argv[0]) -def dir_tree(d='.'): - ''' - Arg: [directory] - scan directory into graph - Ex2: \"write_dot(dir_tree('.'),'tree.dot')\" - ''' - stack = list() - nprev = -1 - g = my_graph() - # all = nx.DiGraph() - # TODO - for path, dirs, files, fds in os.fwalk(d): - (dir, base) = os.path.split(path) - dir = re.sub(r'^\.\/', '', dir) - path = re.sub(r'^\.\/', '', path) - path2 = path.split(os.sep) - # print(path, fds, len(path2)) - if re.match(r'\.repo/', path) or len(path2) > level_limit: - # print("skip", path) - continue - if len(path2) > 1: - # g.add_edge(path2[-2] + str(), path2[-1]) - if g.number_of_edges() > limit: - g.add_edge(dir, '...') - break - g.add_edge(dir, path) - #g.add_node(path, label=path2[-1], xlabel='<'+path+'>') - g.add_node(path, label=path2[-1]) - #g.add_node(path, label=path2[-1], xlabel=path) - print(g.number_of_edges()) - return g - - -def doxygen(*input): - ''' - Arg: - Ex: *.c - ''' - log(' '.join([i for i in input])) - p = run(['doxygen', '-'], stdout=PIPE, - input = "INPUT=" + ' '.join([i for i in input]) + """ - EXCLUDE_SYMBOLS=*310* *311* SOC_ENUM_SINGLE* EXPORT_SYMBOL* - CALL_GRAPH = YES - EXTRACT_ALL = YES - OPTIMIZE_OUTPUT_FOR_C = YES - EXTRACT_STATIC = YES - RECURSIVE = YES - EXCLUDE = html - #GENERATE_TREEVIEW = YES - #HAVE_DOT = YES - #DOT_FONTSIZE = 15 - #CALLER_GRAPH = YES - #INTERACTIVE_SVG = YES - #DOT_TRANSPARENT = YES - #DOT_MULTI_TARGETS = NO - #DOT_FONTNAME = Ubuntu - #CASE_SENSE_NAMES = YES - SOURCE_BROWSER = NO - GENERATE_HTML = NO - GENERATE_LATEX = NO - #QUIET = NO - GENERATE_XML=YES - XML_OUTPUT=xml2""", encoding='ascii') - write_dot(doxygen_xml('xml2'), 'doxygen.dot') - - -def doxygen_xml(a): - g = my_graph() - for x in list(glob.glob(os.path.join(a, "*.xml")) + [a]): - # print(x) - if os.path.isfile(x): - d = xml.dom.minidom.parse(x) - for m in d.getElementsByTagName("memberdef"): - n = m.getElementsByTagName("name")[0].firstChild.data - file = m.getElementsByTagName("location")[0].getAttribute('file') - if file not in files: - print(file) - if n == 'main': - n = file + '::' + n - files[file].append(n) - for r in m.getElementsByTagName("references"): - g.add_edge(n, r.firstChild.data) - for r in m.getElementsByTagName("ref"): - g.add_edge(n, r.firstChild.data) - # referencedby - print(g.number_of_edges()) - return g - - -def doxygen_length(a): - g = my_graph() - for x in list(glob.glob(os.path.join(a, "*.xml")) + [a]): - if os.path.isfile(x): - d = xml.dom.minidom.parse(x) - for m in d.getElementsByTagName("memberdef"): - n = m.getElementsByTagName("name")[0].firstChild.data - location = m.getElementsByTagName("location")[0] - # for r in m.getElementsByTagName("references"): - # g.add_edge(n, r.firstChild.data) - # referencedby - e = location.getAttribute('bodyend') - if not e or e == "-1": - continue - l = int(e) - int(location.getAttribute('bodystart')) - if l < 20: - continue - print(location.getAttribute('bodystart'), n, location.getAttribute('file'), location.getAttribute('bodyfile'), x, file=sys.stderr) - print("{0}:{1}:".format(location.getAttribute('bodyfile'), - location.getAttribute('bodystart')), n, l, "SLOC") - # - return g - - def usage(): + print("Usage:\n") + for c in ["referers_tree", "call_tree", "referers_dep", "call_dep"]: + print(me, c, "") print("\nTry this:\n") print("cd linux/init") print(me, "unittest") - print("\nEmergency termination: ^Z, kill %1") + print(me, "referers_tree nfs_root_data") + print(me, "call_tree start_kernel") + print("Emergency termination: ^Z, kill %1") print() class _unittest_autotest(unittest.TestCase): def test_1(self): write_dot(nx.DiGraph([(1, 2), (2, 3), (2, 4)]), 'test.dot') - g = read_dot("test.dot") + g = read_dot2("test.dot") self.assertEqual(list(g.successors("2")), ["3", "4"]) self.assertTrue(os.path.isdir('include/linux/')) os.chdir('init') - self.assertRegex(popen('srcxray.py referrers_tree nfs_root_data')[-1], - r'.*prepare_namespace.*') - self.assertEqual('initrd_load: prepare_namespace', - popen('srcxray.py referrers_dep nfs_root_data')[-1]) - self.assertEqual('calibrate_delay_converge: __delay', - popen('srcxray.py call_dep start_kernel')[-2]) - self.assertEqual('\t\tcpu_startup_entry', popen( - 'srcxray.py call_tree start_kernel')[-1]) + self.assertEqual('\t\t\t\t\tprepare_namespace ^', popen('srcxray.py referers_tree nfs_root_data')[-1]) + self.assertEqual('initrd_load: prepare_namespace', popen('srcxray.py referers_dep nfs_root_data')[-1]) + self.assertEqual('calibrate_delay_converge: __delay', popen('srcxray.py call_dep start_kernel')[-2]) + self.assertEqual('\t\tcpu_startup_entry', popen('srcxray.py call_tree start_kernel')[-1]) os.chdir('..') self.assertTrue(syscalls().number_of_edges() > 400) # digraph_print: - self.assertEqual("\t\tmount_initrd ^", popen( - "srcxray.py import_cflow init/do_mounts_initrd.c")[-1]) - self.assertRegex(popen( - 'srcxray.py "nx.DiGraph([{1,2},{2,3},{2,4}])"')[-1], - "\t\t4.*") + self.assertEqual("\thandle_initrd ^", popen("srcxray.py import_cflow init/do_mounts_initrd.c")[-1]) + self.assertEqual("\t\t4", popen('srcxray.py "nx.DiGraph([{1,2},{2,3},{2,4}])"')[-1]) def main(): try: ret = False if len(sys.argv) == 1: - #print('Run', me, 'usage') - for m in getmembers(modules[__name__]): - if isfunction(m[1]) and m[1].__module__ == __name__: - d = inspect.getdoc(m[1]) - if not d: - continue - print('\n' + d.replace('Arg:', '\033[1m' + m[1].__name__ + '\033[0m'). - replace('Ex:', '\033[3mExample usage:\033[0m\n' + me + - ' ' + m[1].__name__). - replace('Ex2:', '\033[3mExample usage:\033[0m\n' + me + ' ') - ) - usage() + print('Run', me, 'usage') else: - while sys.argv[1].startswith('--'): - global verbose - global level_limit - log(sys.argv[1][2:]) - if sys.argv[1][2:] == 'verbose': - verbose = True - if sys.argv[1][2:] == 'level_limit': - level_limit = int(sys.argv[2]) - sys.argv = sys.argv[1:] - sys.argv = sys.argv[1:] - a1 = sys.argv[1] sys.argv = sys.argv[1:] - if '(' in a1: + if isinstance(eval(a1), types.ModuleType): + ret = eval(a1+".main()") + elif '(' in a1: ret = eval(a1) # ret = exec(sys.argv[1]) - elif len(sys.argv) == 1 and isinstance(eval(a1), types.ModuleType): - ret = eval(a1 + ".main()") else: - ret = eval(a1 + '(' + ', '.join("'%s'" % (a) - for a in sys.argv[1:]) + ')') + ret = eval(a1 + '(' + ', '.join("'%s'" % (a1) + for a1 in sys.argv[1:]) + ')') if isinstance(ret, nx.DiGraph): digraph_print(ret) - elif isinstance(ret, bool) and ret is False: + if isinstance(ret, bool) and ret is False: sys.exit(os.EX_CONFIG) - else: - if (ret is not None): - print(ret) + # if (ret is not None): + # print(ret) except KeyboardInterrupt: log("\nInterrupted") - # -fdump-rtl-expand if __name__ == "__main__":