[技術] GNU的configure的build、host和target的差別

Written on 2:28 上午 by Yu Lai

相信有編過cross-platform的程式的人,
多多少少會遇到設定這三個參數的時候,
今天正好在編GDB,也就對這3個參數研究了一下。

其實心得可以用一句話來形容這3個:
"讓套件在build下編好,使之在host中執行的target平台版本。"

也就是說:
1. build就是你編這個套件的環境。
通常可以不用設,讓configure自己猜。

2. host就是這個套件的執行環境。
這個通常配cross-compile來編在不同平台執行的套件。
e.g. 要編出在mips-linux下執行的net-snmp套件
./configure --host=mips-linux --prefix=blahblah

3. target是指套件內容的版本或產出物版本。
這個常用於GNU的gcc或binutils等支援不同平台的套件。
e.g. 要編出一個在x86下執行的arm-elf格式的gcc
./configure --host=i686-pc-linux-gnu --target=arm-elf --prefix=blahblah

參考資料: http://www.airs.com/ian/configure/configure_5.html

[技術] C的function call與stack frame心得

Written on 12:00 上午 by Yu Lai

從大二的Program Language中學到stack對於C的function call的實做與功用的概念,
以及各個register的功用,但從未實際地深入了解其中register的變化.
剛好最近T40灌了Ubuntu Linux (x86),就直接寫了些C code,
配合objdump與gdb來trace其中register的變化,於是有了這篇的心得.

首先是複習一下register:
%eip:instruction pointer,用來指到下一個instruction的位置.
%esp:stack pointer,用來指到目前stack的top.
%ebp:Frame pointer,用來指到目前stack frame的開頭.

這次所使用的source code:

#include <stdio.h>
void hi(int a, int b) {
int i = 3;
return;
}
int main(int argc, char *argv[]) {
hi(1, 2);
return 0;
}

我們先透過$ gcc -o test test.c編出test,
然後再透過objdump -d test來觀察disassemble出來的部份:
 08048344 <hi>:
8048344: 55 push %ebp
8048345: 89 e5 mov %esp,%ebp
8048347: 83 ec 10 sub $0x10,%esp
804834a: c7 45 fc 03 00 00 00 movl $0x3,-0x4(%ebp)
8048351: c9 leave
8048352: c3 ret

08048353 <main>:
8048353: 8d 4c 24 04 lea 0x4(%esp),%ecx
8048357: 83 e4 f0 and $0xfffffff0,%esp
804835a: ff 71 fc pushl -0x4(%ecx)
804835d: 55 push %ebp
804835e: 89 e5 mov %esp,%ebp
8048360: 51 push %ecx
8048361: 83 ec 08 sub $0x8,%esp
8048364: c7 44 24 04 02 00 00 movl $0x2,0x4(%esp)
804836b: 00
804836c: c7 04 24 01 00 00 00 movl $0x1,(%esp)
8048373: e8 cc ff ff ff call 8048344 <hi>
8048378: b8 00 00 00 00 mov $0x0,%eax
804837d: 83 c4 08 add $0x8,%esp
8048380: 59 pop %ecx
8048381: 5d pop %ebp
8048382: 8d 61 fc lea -0x4(%ecx),%esp
8048385: c3 ret
8048386: 90 nop

從0x0804835d開始,我們可以看到main()在呼叫hi()時的步驟,
首先先把ebp的值塞進stack中,然後把esp的值塞到ebp裡.
接著把esp減8(因為stack是由高位往低位),再分別把0x2和0x1塞入stack中,
這2個其實就是把hi()所需的變數放入stack中,最後就是call 8048344 <hi>.
接著透過gdb設好breakpoint把stack中的值給印出來.
$ gdb -q test
(gdb) b hi
Breakpoint 1 at 0x804834a
(gdb) r
Starting program: /home/lazyf/test

Breakpoint 1, 0x0804834a in hi ()
Current language: auto; currently asm
(gdb) x/32xw $esp
0xbfb9a074: 0x0804953c 0xbfb9a088 0x08048280 0xb7f95ff4
0xbfb9a084: 0xbfb9a098 0x08048378 0x00000001 0x00000002
0xbfb9a094: 0xbfb9a0b0 0xbfb9a108 0xb7e61450 0xb7fc8ce0
0xbfb9a0a4: 0x080483a0 0xbfb9a108 0xb7e61450 0x00000001
0xbfb9a0b4: 0xbfb9a134 0xbfb9a13c 0xb7facb38 0x00000000
0xbfb9a0c4: 0x00000001 0x00000000 0x080481f5 0xb7f95ff4
0xbfb9a0d4: 0xb7fc8ce0 0x00000000 0xbfb9a108 0x67416081
0xbfb9a0e4: 0xd8282a91 0x00000000 0x00000000 0x00000000
(gdb)

從stack內的值我們可以觀察到,其實call指令所做的動作就是把下一筆instruction的
address(eip)給push進stack裡(0x08048378被放入0xbfb9a088中),接著再把call的address
塞到eip再執行它.

接著到了hi()中,和main()一樣的先把ebp塞入stack中,然後把把esp的值塞到ebp裡.
從這裡我們可以知道,一個function開始時,會先把上一個function的ebp放入stack中,
接著馬上設定自己的ebp.從這裡可以用來確保目前所在function的ebp的值的正確性,
以及保存之後要return時上一個function的ebp的值.

在hi()中把ebp設定好後,它先在stack中allocate了16個byte來使用,接著我們看到了
在ebp-4的位置上被填入了0x3的值,也就是我們在程式中宣告的變數int i = 3;的實做.

最後是leave指令和ret指令所實做出來的return;.在這裡leave指令的操作相當於
把ebp的值放到esp中,然後從stack中pop出值來放到ebp裡,而ret指令的操作則相當於從
stack中pop出值來放到eip裡.也就是說除了eip外,esp和ebp都回到呼叫hi()之前的狀況.
完成hi()的呼叫.

另外,如果hi()有值需要被return時,通常會透過eax register來傳遞.
也就是說在$lt;hi>中的leave指令前會加入mov xxx,%eax指令,
在<main>中call <hi>指令的下一個指令會是mov %eax,yyy指令讀出eax放入yyy中
和mov $0x0,%eax指令把eax清空.

以上就是我從gdb與objdump中所觀察到的一個C的function被呼叫的過程.
如內容有所錯誤,煩請有看到的人不吝賜教.Thanks.

[技術] Ubuntu的dash

Written on 4:39 下午 by Yu Lai

這幾天把舊的T40裝了Ubuntu,用一用發現有些怪怪的地方.
原本可以用的script有些怪怪的,後來查了一下才發現是dash在做怪.
Ubuntu為了加速開機,使用了dash來取代bash成為/bin/sh.
但dash實做的有些不完整,自然就被它給婊到了.

解決方法除了使用指令$ sudo dpkg-reconfigure dash外
也可以用ln手動把/bin/sh -> /bin/dash 改回 /bin/sh -> /bin/bash即可.

[技術] Google Code Prettify

Written on 2:41 上午 by Yu Lai

今天在部落格裡加入了google-code-prettify。
http://code.google.com/p/google-code-prettify/
所以現在在文章中的程式碼,只要透過<pre class="prettyprint">...</pre>的方式,即可得到有highlight效果的呈現。以下是demo:

int main() {
printf("Hello World");
return 0;
}

[閒聊] 網誌改版

Written on 7:24 下午 by Yu Lai

買了Dell E228WFP後才發現,
原本的template已經被我改的只能用在1024x768下,
在寬螢幕下顯示都跑掉了.

於是就改版一下囉, 換了個template,
感覺還不錯 ^^