8048374: 8d 4c 24 04 lea 0x4(%esp),%ecx /*将堆栈的原栈顶保存*/
8048378: 83 e4 f0 and $0xfffffff0,%esp /*将现在的堆栈以4字节对齐*/
804837b: ff 71 fc pushl 0xfffffffc(%ecx) /*0xfffffffc是-4,将原堆栈入栈*/
804837e: 55 push %ebp /*原堆栈基地址入栈*/
804837f: 89 e5 mov %esp,%ebp /*换入新堆栈基地址(就是当前的栈顶)*/
8048381: 51 push %ecx /*远来的堆栈栈顶入栈*/
8048382: 83 ec 10 sub $0x10,%esp /*现在的堆栈栈顶下移 0x10就是4个字节*/
8048385: c7 45 f4 01 00 00 00 movl $0x1,0xfffffff4(%ebp) /*移入数据 1*/
804838c: c7 45 f8 02 00 00 00 movl $0x2,0xfffffff8(%ebp) /*移入数据 2*/
8048393: 83 c4 10 add $0x10,%esp /*栈顶返回到原来的存放 %ecx的地址*/
8048396: 59 pop %ecx /*出栈*/
8048397: 5d pop %ebp /*%ebp出栈*/
8048398: 8d 61 fc lea 0xfffffffc(%ecx),%esp /*同上,这是返回远来堆栈栈顶*/
804839b: c3 ret /*返回*/
804839c: 90 nop
804839d: 90 nop
804839e: 90 nop
804839f: 90 nop
没有见到void 的那一行操作,看样子只是gcc检查出现错误才会出现。
[/code]
unsigned long __lockfunc _raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
return __raw_spin_lock_irqsave(lock); /* include/linux/spinlock_api_smp.h*/
}
EXPORT_SYMBLE(_raw_spin_lock_irqsave); /*这是输出到内核符号表*/
static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
unsigned long flags;
lock_irq_save(flags);/*
preempt_disable();
spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
#ifdef CONFIG_LOCKDEP
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);/*检测是否死锁的宏定义 linux-2.6.39.1 ..../lockdep.h/*/
#else
do_raw_spin_lock_flags(lock, flags);
#endif
return flags;
}
#define LOCK_CONTENDED(_lock, try, lock)
\
do {
\
if (!try (_lock)) { /*Here is the do_raw_spin_trylock(lock) */
\
lock_contended ( &(_lock)->dep_map, _RET_IP_); /* `uname -r`/....lockdep.c*/
\
lock(_lock);
\
}
\
lock_acquired( &(_lock)->dep_map, _RET_IP_);
}while(0)
void lock_contended(struct lockdep_map *lock, unsigned long ip) /*检验*/
{
unsigned long flags;
if (unlikely(! lock_stat)) /*linux-2...../compiler.h, it is used here, it will be have return value 0 or 1 0.0 */
return ;
if(unlikely(current->lock_recursion))
return ;
raw_local_irq_save(flags);
check_flags(flags);
current->lockdep_recursion = 1;
trace_lock_contended(lock, ip);
__lock_contended(lock, ip);
current->lockdep_recursion = 0;
raw_local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(lock_contended);
#ifndef unlikely
# define unlikely(x) (__builtin_constant_p(x) ? ! !(x) : __branch_check__(x, 0)) /*__builtin_constant_p()是gcc 专用函数 如果x在编译的时候就能获得常值,则为TRUE;如果是变量则为FALSE ||||||||||||||||||__branch_check__(x, expect) 同一个文件*/
#endif
#define __branch_check__(x, expect) ({ \ /*记录当前的trace点,并用后面的函数ftrace_likely_update记录likely的正确性,结果保存在ring buffer中。*/
int ______r;
\
static int ftrace_branch_data /*定义在本文件中*/
\
__attribute__((__aligned__(4)))
\
__attribute__((section("_ftrace_annotated_brach"))) \
________f = {
\
.func = __func___, /*这是宏定义见下面*/
\
.file = __FILE__, /*这些元素都是标志trace节点*/
\
.line = __LINE__,
\
};
\
______r = likely_notrace(x); /*likely_notrace和unlilely_notrace宏使用__builtin_expect函数,告诉编译器程序设计者期望的比较结果,以便编译器对代码进行优化,改变汇编中的跳转语句*/
\
ftrace_likely_update(&______f, ______r, expect); \
_____r;
\
})
#define likely_notrace(x) __builtin_expect(! !(x), 1) /*期望运行可以说这里对应到 jne ,如果命中了,那么就返回1。*/
#define unlikely_notrace(x) __builtin_expect(! !(x), 0) /*这里对应到je,如果期望不继续追逐*/
struct ftrace_branch_data { /*结构体用于记录ftrace branch的trace记录*/
const char *func;
const char *file;
unsigned line;
union {
struct {
unsigned long correct;
unsigned long incorrect;
};
struct {
unsigned long miss;
unsigned long hit;
};
unsigned long miss_hit[2];
};
};
0000000
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 8b 45 08 mov 0x8(%ebp),%eax /*这应该是取那个测试参数*/
6: 83 05 38 00 00 00 01 addl $0x1,0x38
d: 83 15 3c 00 00 00 00 adcl $0x0,0x3c
14: 85 c0 test %eax,%eax
16: 74 15 je 2d
18: 83 05 40 00 00 00 01 addl $0x1,0x40
1f: b8 05 00 00 00 mov $0x5,%eax
24: 83 15 44 00 00 00 00 adcl $0x0,0x44
2b: 5d pop %ebp
2c: c3 ret /*注意这里如果没有跳转,就已经返回了*/
---------------------------
以下就是修改地址部分*/
2d: 83 05 48 00 00 00 01 addl $0x1,0x48/*48 00 00 00 是32位地址,储存地址是大端模式。*/
34: b8 06 00 00 00 mov $0x6,%eax /*修改地址,以变成不同的分支*/
39: 83 15 4c 00 00 00 00 adcl $0x0,0x4c
40: 5d pop %ebp
41: c3 ret
42: 8d b4 26 00 00 00 00 lea 0x0(%esi,%eiz,1),%esi
49: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi /*这里是nop指令的汇编写法,占用可以看到是7个字节,而运行长字节指令快于多个短字节指令,0*0所以就用快的!*/
对于__FILE__,__LINE__,__func__这样的宏,在调试程序时是很有用的,因为你可以很容易的知道程序运行到了哪个文件的那一行,是哪个函数。
下面一个例子是打印上面这些预定义的宏的。
#include
#include
void why_me();
int main()
{
printf( "The file is %s.\n", __FILE__ );
printf( "The date is %s.\n", __DATE__ );
printf( "The time is %s.\n", __TIME__ );
printf( "This is line %d.\n", __LINE__ );
printf( "This function is %s.\n", __func__ );
why_me();
return 0;
}
void why_me()
{
printf( "This function is %s\n", __func__ );
printf( "The file is %s.\n", __FILE__ );
printf( "This is line %d.\n", __LINE__ );
} ./funcline
The file is funcline.c
The date is Sep 28 2011
The time is 10:21:54.
This is line 15
This function is main.
This function is why_me
The file is funcline.c
This is line 25