UPDATE
现在在读博士,方向Computer architecture,具体而言GPGPUs architecture。个人主页 (http://zhaoxiahust.github.io/)。
Xwindows和一些编码
Latex xeCJK安装
最近在小某某的感召下用起了shell编程,进而拷来了texlive,中文支持的时候出了些小小的问题,现在分享下简单的解决方法。
先是利用安装盘里的texlive的包install.sh到本地硬盘,做得貌似就是复制i386的工作?
简单的英文文档支持没有问题,为了支持中文
cp -r /usr/local/texlive/2012/texmf-dist/tex/xelatex/xecjk /usr/local/texlive/texmf-local/tex/xelatex/ 中,
注意root权限
利用texlive中的命令/usr/local/texlive/2012/bin/i386-linux/mktexlsr 更新包信息
简单的测试程序如下:
1.tex
关于C语言的函数调用机制
今天在sina Weibo上看到一个人发的一道面试题目,有关于被调用函数中局部变量的若干问题。于是我回忆函数的调用机制,但是感觉有点模糊,以前在做MIT的JOS的时候碰到过,但是记忆有些模糊了,于是利用一个简单的程序进行了过程的重温。
OS是gentoo,GCC-4.5.3--gcc -S *.c 进行反汇编
源代码如下
#include <stdio.h> struct tree{ int a; int b; };//之所以定义结构体是想更深入的了解下 struct tree foo(int a, char b) { struct tree m = {1,2}; m.a = a; m.b = b; return m; } int main(void) { int a = 2; char b = 3; struct tree m = {4,4}; m = foo(a, b); a = m.a; }
.file "1.c" .text .globl foo .type foo, @function foo: pushl %ebp movl %esp, %ebp subl $20, %esp movl 8(%ebp), %ecx movl 16(%ebp), %eax movb %al, -20(%ebp) movl $1, -8(%ebp) movl $2, -4(%ebp) movl 12(%ebp), %eax movl %eax, -8(%ebp) movsbl -20(%ebp), %eax movl %eax, -4(%ebp) movl -8(%ebp), %eax movl -4(%ebp), %edx movl %eax, (%ecx) movl %edx, 4(%ecx) movl %ecx, %eax leave ret $4 .size foo, .-foo .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $28, %esp movl $2, -4(%ebp) movb $3, -5(%ebp) movl $4, -16(%ebp) movl $4, -12(%ebp) movsbl -5(%ebp), %edx leal -16(%ebp), %eax movl %edx, 8(%esp) movl -4(%ebp), %edx movl %edx, 4(%esp) movl %eax, (%esp) call foo subl $4, %esp movl -16(%ebp), %eax movl %eax, -4(%ebp) leave ret .size main, .-main .ident "GCC: (Gentoo 4.5.3-r2 p1.5, pie-0.4.7) 4.5.3" .section .note.GNU-stack,"",@progbits
其中指令比较有难度的就是
call 函数调用指令,在main函数中我们调用了foo函数,对应的汇编指令就是
call foo,操作系统做的工作就是sp=sp-4,然后将ip入栈,更换ip指向foo的指令
leave,将ebp的值赋给esp,然后pop出来ebp。注意pop 指令先读取出esp 对应栈单元的值,然后esp=esp+4;push指令先esp=esp-4,在将值存入esp所指的栈单元。
ret,函数返回指令,根据当前的esp读取出eip的值,然后返回主函数的指令
下面根据汇编代码和内存栈的变化说明程序的执行过程以及函数调用如何得到返回值
执行到调用call foo时内存栈的情况如下
注意leal -16(%ebp), %eax ;将ebp-16的值赋给eax,通过记录结构体内存单元的地址实现返回值的使用。
call指令执行过后,执行到处理返回值之前,内存单元的情况如:
下面是函数是如何将返回值传递给主函数的
通过ebp,esp的变换,在调用函数中实现了返回值的传递。
下面执行到leave指令,复原esp,ebp,然后ret返回到main函数中。
上诉实验说明了很多东西以前貌似懂了,但是讲的话难度还是很大。反正赋闲在家,有心情的话还想把JOS重新做一边,顺便把很多书上的东西巩固一下。
KLEE小解
今天博士检查了我的PPT,各种不合格,需要努力的地方还有很多
现在针对PPT中没有给出的两个重要问题做下解释:
1.KLEE的工作流程
2 KLEE为什么是单线程的
1.KLEE的工作流程
我们从最普通的命令行说起
klee -libc=uclibc -posix-runtime *.bc
启动klee程序,读入参数
在LinkModule的时候,判断link哪个库,这里我们link的是uclibc和posix-runtime,注意link的先后顺序
然后初始化变量
进入runFuncitonAsMain进行运行
主要的环节在
while(state)//////判断sate是否全部终结
{
从Executor中的一堆state中根据规则select出来一个state
executeInstruction(state.instruciton, state);
update(state)
}
在executeInstruction中根据不同的指令,执行不同的动作(相当于KLEE解释.bc文件)
如果遇到函数调用,则判断函数是外部函数还是内部函数,如果是外部函数,则调用外部库函数或者handler一下
如果是内部函数,则Frame入栈,state.pc更改,随着下一次state的选择执行调用函数的指令
当遇到返回指令的时候,如果state.stack为空,则solve 出constraint
若state.stack不为空,则相当于内部函数返回,pop Frame,更改state.pc
如果遇到分支指令,则根据condition,看是否必要在fork中生成新的falsestate,update(state)时添加新的状态
2KLEE的单线程
KLEE执行函数调用的方法是保留栈stack,popFrame和pushFrame
并没有为函数调用开启新的state或者其他特殊方法
当遇到pthread_create函数的时候,系统没有在uclibc和posix-runtime的库中链接到相应的函数于是直接调用了
系统函数pthread_create导致了KLEE的崩溃!!
VIM之cscope和taglist
一直想尝试下放弃sourceinsight,今天中午终于有时间试了下cscope和taglist插件
cscope主要是生成文档之间和函数之间的以来关系,比ctag要强大,taglsit主要是显示像sourceinsight一样的声明信息
cscope可以通过yum install安装
taglist主要是vim的插件,官网上可以下载,放到~/.vim/下(如果没有,则创建,记得打开vim的后,输入helptags ~/.vim/doc/ ,这样才能查看 help文档)
在工程的根目录下面使用cscope的命令
find -name "*.h" -o -name "*.c" -o -name "*.cpp" > cscope.file
cscope -bkq -i cscope.file
ctags -R
分别查找到工程目录文件,添加到cscope.file中,然后根据它里面的内容,生成依赖关系
taglist的配置,可以写到/etc/vimrc 里面
let Tlist_Ctags_Cmd = '/usr/bin/ctags'
let Tlist_Show_One_File = 1
let Tlist_Exit_OnlyWindow = 1 仅标签页存在则关闭
在命令模式输入TlistOpen打开
ctrl+w可以在左右窗口切换
ctrl+t生成显示该定义的新的标签页,命令行模式输入tabn,tabp可切换
KLEE-之函数调用
关于函数的调用在klee使用中的体现
klee -libc=uclibc -posix-runtime *.bc
在executeInstrucion()中
通过判断instruction的类型,区分了call,和invoke
然后通过判断是不是直接的函数调用(是否为函数指针??)
如果是直接的函数调用,则调用函数executeCall(),如果是非直接,则做进一步处理,待考证
executeCall()
{
if(f->isDeclaration())//////////如果函数仅仅有函数头, 即函数是外部函数,则调用
callExternFunction();
{
在这里面判断是否为定义的特殊函数例如klee_make_symbolic是,间接调用相应的函数
否,则使用系统调用相应的函数
}
else
{
函数的定义包含在module中,注意,这里的定义包含其实分为两种情况
1.函数为自己定义的函数,这样刚开始的时候函数即在里面
2.函数是外部函数,例如puts之类,但是因为我们使用klee的时候,加上了参数uclibc,和runPosixTime,所以在原module和
库函数链接 的时候,就把定义链接了进去(经过实验,不知道为嘛printf没有被链接进去???)
注意klee::main.cpp中链接的顺序,先是链接uclibc,将fopen之类的函数展开,在这里是展开为open
然后链接PosixRuntime库,在runTime/Fd_32.c中有open的定义,调用了
fd.c中的__fd_open函数,在这里面就判断了文件名参数path是否为symbolic
是,则使用klee定义的symbolic 模块
否,则调用真正的系统调用
}
}
这样大概解释了pthread_create的调用过程
因为uclibc中的libc库没有pthread_create的定义,而且specialHanlder也没有,就直接进入了symtem调用最直接的 pthread_create
KLEE--constraint与state的关系
在 executor.cpp中,有run函数,一切程序的运行的驱动都是从这里开始的
line:2460
while (!states.empty() && !haltExecution)
{
line2465:
KLEE源码解析之klee_make_symbolic跟踪
使用klee时,一般要利用klee_make_symbolic函数,将要跟踪的变量标记为symbolic,但是klee是如何找到这个函数,并且对应标记的呢。。。。。
把klee_make_symbolic使用的分为两个过程,1。绑定 2.调用
1.绑定
在main.cpp中
Executor.cpp
进入runFunctionAsMain函数
line3257
fedora16源设置
安装插件yum install yum-fastestmirror,他会自动寻找最快的源《或者直接下载163的源,fedora-163.repo和fedora-updates-163.repo, 放入/etc/yum.repos.d/,将其他的源备份为.save》。第三方源
su -c 'yum localinstall --nogpgcheck http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm
http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm'
,主要是安装闭源驱动。
之后就是yum更新,今天找到了传说中的axel,多线程下载,TNND,真的很快。方法如下:
先yum install axel,然后下载yum相关配置文件
cd /etc/yum/pluginconf.d/
axel http://cnfreesoft.googlecode.com/svn/trunk/axelget/axelget.conf
cd /usr/lib/yum-plugins/
axel http://cnfreesoft.googlecode.com/svn/trunk/axelget/axelget.py
这样用yum更新就是多线程下载了。
更新过程中可能会出现:
错误详细:[Errno 14] Could not open/read file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmfusion-free-fedora-15-i386
用yum update --nogpgcheck即可。
转自internet