2015年10月15日星期四

linux下的调试工具ltrace与strace

ltrace能够跟踪进程的库函数调用,它会显现出哪个库函数被调用,而strace则是跟踪程序的每个系统调用.
下面是一个ltrace与strace的对比
1)系统调用的输出对比
我们用输出hello world的程序做如下测试:
#include <stdio.h>
int
main ()
{
printf("Hello world!\n");
return 0;
}
gcc hello.c -o hello
用ltrace跟踪hello程序,如下:
ltrace ./hello
__libc_start_main(0x8048354, 1, 0xbf869aa4, 0x8048390, 0x8048380 <unfinished ...>
puts("Hello world!"Hello world!) = 13
+++ exited (status 0) +++
注:我们看到程序调用了puts();库函数做了输出.
用strace跟踪hello程序,如下:
strace ./hello
execve("./hello", ["./hello"], [/* 30 vars */]) = 0
brk(0) = 0x83d4000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f8a000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=80846, ...}) = 0
mmap2(NULL, 80846, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f76000
close(3) = 0
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000?\270"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1576952, ...}) = 0
mmap2(0xb6e000, 1295780, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6e000
mmap2(0xca5000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x137) = 0xca5000
mmap2(0xca8000, 9636, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xca8000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f75000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7f756c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xca5000, 8192, PROT_READ) = 0
mprotect(0xb6a000, 4096, PROT_READ) = 0
munmap(0xb7f76000, 80846) = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f89000
write(1, "Hello world!\n", 13Hello world!
) = 13
exit_group(0) = ?
Process 2874 detached
注:我们看到程序调用write()系统调用做了输出,同时strace还把hello程序运行时所做的系统调用都打印出来了.
同样的ltrace也可以把系统调用都打印出来,如下:
ltrace -S ./hello
SYS_execve(NULL, NULL, NULL) = 0xffffffda
SYS_brk(NULL) = -38
SYS_mmap2(0, 4096, 3, 34, -1) = -38
SYS_access(0xb6798f, 4, 0xb6afc0, 0, 0xb6b6b4) = -38
SYS_open("/etc/ld.so.cache", 0, 00) = -38
SYS_fstat64(3, 0xbfba5414, 0xb6afc0, -1, 3) = -38
SYS_mmap2(0, 80846, 1, 2, 3) = -38
SYS_close(3) = -38
SYS_open("/lib/libc.so.6", 0, 027756452364???, 512) = -38
SYS_read(3, ) = -38
SYS_fstat64(3, 0xbfba5478, 0xb6afc0, 4, 1) = -38
SYS_mmap2(0xb6e000, 0x13c5a4, 5, 2050, 3) = -38
SYS_mmap2(0xca5000, 12288, 3, 2066, 3) = -38
SYS_mmap2(0xca8000, 9636, 3, 50, -1) = -38
SYS_close(3) = -38
SYS_mmap2(0, 4096, 3, 34, -1) = -38
SYS_set_thread_area(0xbfba5960, 0xb7f5e6c0, 243, 0xb6afc0, 0) = -38
SYS_mprotect(0xca5000, 8192, 1, 7676, 0xca6e74) = -38
SYS_mprotect(0xb6a000, 4096, 1, 896, 0) = -38
SYS_munmap(0xb7f5f000, 80846 <unfinished ...>
__libc_start_main(0x8048354, 1, 0xbfba5dd4, 0x8048390, 0x8048380 <unfinished ...>
puts("Hello world!" <unfinished ...>
SYS_fstat64(1, 0xbfba5c20, 0xca6ff4, 0xca74c0, 0xca74c0) = 0
SYS_mmap2(0, 4096, 3, 34, -1) = 0xb7f72000
SYS_write(1, "Hello world!\n", 13Hello world!
) = 13
<... puts resumed> ) = 13
SYS_exit_group(0 <no return ...>
+++ exited (status 0) +++
注:我们看到它实际是用SYS_write系统调用来做打印输出,其实write()函数是SYS_write的封装,SYS_write是真正的系统调用.

二)ltrace/strace的耗时
ltrace -c dd if=/dev/urandom of=/dev/null count=1000
1000+0 records in
1000+0 records out
512000 bytes (512 kB) copied, 2.31346 seconds, 221 kB/s
% time seconds usecs/call calls function
------ ----------- ----------- --------- --------------------
84.88 4.942763 4942 1000 read
9.41 0.548195 548 1000 write
5.06 0.294716 294 1001 memcpy
0.11 0.006365 2121 3 __fprintf_chk
0.09 0.004969 4969 1 dcgettext
0.08 0.004850 808 6 strlen
0.05 0.002667 2667 1 setlocale
0.04 0.002579 644 4 sigaction
0.03 0.001869 467 4 close
0.03 0.001825 912 2 open64
0.03 0.001519 759 2 malloc
0.02 0.001187 593 2 __sprintf_chk
0.02 0.001176 588 2 clock_gettime
0.02 0.001169 389 3 __errno_location
0.02 0.001012 506 2 dcngettext
0.01 0.000814 814 1 lseek64
0.01 0.000757 757 1 getopt_long
0.01 0.000744 744 1 textdomain
0.01 0.000742 247 3 strchr
0.01 0.000634 634 1 __strtoull_internal
0.01 0.000602 602 1 getpagesize
0.01 0.000542 271 2 localeconv
0.01 0.000340 340 1 fclose
0.01 0.000300 300 1 memmove
0.00 0.000228 114 2 sigismember
0.00 0.000184 184 1 getenv
0.00 0.000170 85 2 sigaddset
0.00 0.000148 74 2 free
0.00 0.000093 93 1 bindtextdomain
0.00 0.000090 90 1 sigemptyset
0.00 0.000090 90 1 __cxa_atexit
0.00 0.000088 88 1 __ctype_b_loc
0.00 0.000074 74 1 __fpending
------ ----------- ----------- --------- --------------------
100.00 5.823501 3057 total
注:
使用-c选项,ltrace输出由进程创建的库调用,输出结果以调用过程的时间为准进行排序,因为是从urandom设备上读,这是一种产生随机数的设备,完成后,写入null设备.
所以读过程花费了较多的时间.
使用ltrace去捕获运行时函数,就好像在进程上系上了一个调试工具,它占据了ltrace大量的时间,这里ltrace一共消耗了5.8秒
我们再来看一下strace所花费的时间,如下:
strace -c dd if=/dev/urandom of=/dev/null count=1000
1000+0 records in
1000+0 records out
512000 bytes (512 kB) copied, 0.894482 seconds, 572 kB/s
Process 3049 detached
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
82.85 0.159393 159 1005 read
15.07 0.028995 29 1003 write
0.78 0.001494 1494 1 execve
0.42 0.000814 136 6 rt_sigaction
0.23 0.000446 41 11 1 close
0.23 0.000435 73 6 fstat64
0.21 0.000412 32 13 mmap2
0.21 0.000408 29 14 6 open
0.00 0.000000 0 1 1 access
0.00 0.000000 0 3 brk
0.00 0.000000 0 2 munmap
0.00 0.000000 0 1 uname
0.00 0.000000 0 4 mprotect
0.00 0.000000 0 1 _llseek
0.00 0.000000 0 1 rt_sigprocmask
0.00 0.000000 0 1 getrlimit
0.00 0.000000 0 1 set_thread_area
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 2 clock_gettime
0.00 0.000000 0 1 set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00 0.192397 2078 8 total
注:
strace一共消耗了0.19秒,strace把性能提升了30倍,这主要是strace在跟踪系统调用的时候不需要动态库,而ltrace是根据动态库来分析程序运行的.
所以ltrace也只能跟踪动态库,不能跟踪静态库.
事实上我们用ltrace和strace都可以发现程序在哪个系统调用时发生了性能瓶径.
ltrace用-T,而strace也用-T.
三)ltrace与strace的相同点
ltrace与strace都可以指定PID,即对运行中的程序进行跟踪.
ltrace -p PID与strace -p PID
ltrace与strace都可以跟踪程序fork或clone子进程.
ltrace是用-f参数,而strace是用-f(fork/clone)和-F(vfork).
Source:http://blog.csdn.net/macky0668/article/details/6839520

2015年5月28日星期四

Open Security Research: Getting Started with WinDBG - Part 1

Open Security Research: Getting Started with WinDBG - Part 1: By Brad Antoniewicz . WinDBG is an awesome debugger. It may not have a pretty interface or black background by default, but it still one...

2015年4月14日星期二

Python Tips

isinstance(object, classinfo)

Return true if the object argument is an instance of the classinfo argument, or of a (direct, indirect or virtual) subclass thereof. Also return true if classinfo is a type object (new-style class) and object is an object of that type or of a (direct, indirect or virtual) subclass thereof. If object is not a class instance or an object of the given type, the function always returns false. If classinfo is neither a class object nor a type object, it may be a tuple of class or type objects, or may recursively contain other such tuples (other sequence types are not accepted). If classinfo is not a class, type, or tuple of classes, types, and such tuples, a TypeError exception is raised.
Changed in version 2.2: Support for a tuple of type information was added.

Source:https://docs.python.org/2/library/functions.html

Python Tips

About '__init__.py'

python的每个模块的包中,都有一个__init__.py文件,有了这个文件,我们才能导入这个目录下的module。
那么,__init__.py还有什么别的功能呢?
其实,__init__.py里面还是可以有内容的,我们在导入一个包时,实际上导入了它的__init__.py文件。
我们可以再__init__.py文件中再导入其他的包,或者模块。
[python]
import readers

import writers

import commands

import users

import meta

import auth

import admin


这样,当我们导入这个包的时候,__init__.py文件自动运行。帮我们导入了这么多个模块,我们就不需要将所有的import语句写在一个文件里了,也可以减少代码量。
不需要一个个去导入module了。
__init__.py 中还有一个重要的变量,叫做 __all__。我们有时会使出一招“全部导入”,也就是这样:
from PackageName import *
这时 import 就会把注册在包 __init__.py 文件中 __all__ 列表中的子模块和子包导入到当前作用域中来。比如:
#文件 __init__.py

__all__ = ["Module1", "Module2", "subPackage1", "subPackage2"]

source:http://www.2cto.com/kf/201204/129388.html

2015年3月8日星期日

Python Tips

How to easily convert a list to a string for display

There are a few useful tips to convert a Python list (or any other iterable such as a tuple) to a string for display.

First, if it is a list of strings, you may simply use join this way:
>>> mylist = ['spam', 'ham', 'eggs']
>>> print ', '.join(mylist)
spam, ham, eggs


Using the same method, you might also do this:
>>> print '\n'.join(mylist)
spam
ham
eggs


However, this simple method does not work if the list contains non-string objects, such as integers.
If you just want to obtain a comma-separated string, you may use this shortcut:
>>> list_of_ints = [80, 443, 8080, 8081]
>>> print str(list_of_ints).strip('[]')
80, 443, 8080, 8081


Or this one, if your objects contain square brackets:
>>> print str(list_of_ints)[1:-1]
80, 443, 8080, 8081


Finally, you may use map() to convert each item in the list to a string, and then join them:
>>> print ', '.join(map(str, list_of_ints))
80, 443, 8080, 8081
>>> print '\n'.join(map(str, list_of_ints))
80
443
8080
8081


source: http://www.decalage.info/en/python/print_list

Python Tips


IOError: [Errno 22] invalid mode ('r') or filename

test_file=open('c:\\Python27\test.txt','r')
test_file=open(r'c:\Python27\test.txt','r')


or double the slashes:
test_file=open('c:\\Python27\\test.txt','r')

or use forward slashes instead:
test_file=open('c:/Python27/test.txt','r')