顯示具有 Embedded 標籤的文章。 顯示所有文章
顯示具有 Embedded 標籤的文章。 顯示所有文章

2018年3月4日 星期日

2016年10月12日 星期三

[QEMU] 在 Ubuntu 平台執行 ARM 平台的某個執行檔

本篇提供一個簡單的qemu執行範例,可以直接執行嵌入式系統(ARM)的執行檔,並說明如何結合基本的檔案輸入輸出,以及如何使用gdb進行除錯。

安裝 qemu
$ sudo apt-get install qemu-user

2016年10月6日 星期四

[Embedded] 取出背景行程的 STDOUT 訊息

在 linux 系統,若需要觀察系統中某行程的輸出訊息 (stdout, stderr),常見的做法是在執行檔案時直接將輸出導入至某個檔案。如下:
1. 分別導出 stdout 與 stderr
executable_file > stdout.txt 2> stderr.txt
2. 將 stdout 與 stderr 導出至同一檔案
executable > output.txt 2>&1
如果是目前已經在執行的行程,要如何在不重啟的情況之下,將 stdout, stderr 轉導向其他檔案呢?比方說某個正在執行的 CGI 程式,如何知道其輸出訊息?

2016年6月3日 星期五

[Embedded] 檢視 message queue 資訊

Linux 下的 IPC 運作若使用 message queue,有兩種 message queue 可用,分別是 SYSTEM V MESSAGE QUEUE 與 POSSIX MESSAGE QUEUE,本篇將介紹如何確認 message queue 中的資訊。

2016年3月9日 星期三

[Embedded] how to check heap corruption

上週的 linux news 提到 iOS 上的一個問題,Analysis of iOS & OS X Vulnerability: CVE-2016-1722,指出了 heap overflow 的問題。這篇新聞提醒了自己,應該要將之前的實戰經驗做一下整理了。本篇會針對如何找到 heap corruption 的方法作一整理。

2015年4月27日 星期一

[Embedded] 如何替換系統內預設的 memcpy 函數

最近使用 perf 替手邊的嵌入式系統進行效能分析,發現系統內最常被用到的函數是 memcpy(),若能夠優化此函數,應該可以改善系統效能吧。以下記錄整個實驗過程。

1. 系統效能分析
編譯perf的方法可參考此篇文章。使用 "perf top" 可以得知觀察系統當前的狀態,找到最耗時的函數。 
"perf top"原文說明如下:

The default sampling event is cycles and default order is descending number of samples per symbol, thus perf top shows the functions where most of the time is spent. By default, perf top operates in processor-wide mode, monitoring all online CPUs at both user and kernel levels. It is possible to monitor only a subset of the CPUS using the -C option.
下圖為"perf top"的執行結果,由圖中可得知 libc-2.10.1.so 內的 memcpy 函數是整個系統最耗時的部分,因此我將針對此函數進行分析,評估是否有優化的空間。

2. memcpy 函數分析
首先需要先檢視 libc-2.10.1對memcpy的實作方式,glibc 原始碼可至 http://ftp.gnu.org/gnu/glibc/ 下載。我分別下載了 libc-2.10.1 和 libc-2.21 的程式碼並進行比較。其主要差別在於libc-2.10.1使用C語言撰寫,而 libc-2.21將memcpy則會使用ARM的組合語言。 
  • 比較 glibc-2.10.1\string\memcpy.c 與 glibc-2.21\string\memcpy.c,其內容幾乎一樣。 
  • 但 glibc-2.21 針對 memcpy 新增了 ARM 的組語版本 (\glibc-2.21\sysdeps\arm\memcpy.S),當編譯ARM版本的 libc 時,便會選擇編譯組語版本的 memcpy。 
合理的推論,在 ARM 架構下, \arm\memcpy.S 的運作效能應該優於 \string\memcpy.c

3. 如何替換 libc 內的 memcpy
為了簡單,我並沒有使用 glibc-2.21 的 memcpy,我直接從 android source code中取出對應的 memcpy.S,用來練習置換 libc memcpy,原始程式可至 github 取得。 
方法一:直接 link 自行改寫的 memcpy library,用法如下:
$(CC) memcpy_test.o memcpy.o -o memcpy_test
$ arm-none-linux-gnueabi-readelf -s ./memcpy_test
  110: 00008520     0 FUNC    GLOBAL DEFAULT   12 memcpy
  125: 000083f0     0 FUNC    GLOBAL DEFAULT  UND malloc@@GLIBC_2.4 
方法二:透過設定 LD_PRELOAD 可切換動態連結時所尋找的 library 順序
$(CC) memcpy_test.o  -o memcpy_test
$ arm-none-linux-gnueabi-readelf -s ./memcpy_test
  104: 000083f8     0 FUNC    GLOBAL DEFAULT  UND memcpy@@GLIBC_2.4
  110: 00008404     0 FUNC    GLOBAL DEFAULT  UND malloc@@GLIBC_2.4 
$ export LD_PRELOAD=/tmp/test/mem_practice/libmymemcpy.so
$ ./memcpy_test  (使用自行編譯的 memcpy) 
$ export LD_PRELOAD=
$ ./memcpy_test  (使用 libc 的 memcpy)
可透過下列命令切換不同的 memcpy 並測試效能
$ export LD_PRELOAD=/tmp/test/mem_practice/libmymemcpy.so
$ ./perf bench mem all 
$ export LD_PRELOAD=
$ ./perf bench mem all 
4. 針對整個系統,更換 user space 所使用的 memcpy
若確定修改過後的 memcpy library 效能的確較佳,則可以修改 /etc/ld.so.preload,讓系統每次在作 dynamic link 時,總是先尋找自行撰寫的 memcpy library. 
ld.so.preload 的內容舉例如下:
/lib/libmymemcpy.so

參考資料
  1. http://stackoverflow.com/questions/27171485/various-glibc-and-linux-kernel-versions-compatibility
  2. http://stackoverflow.com/questions/9107259/how-to-replace-c-standard-library-functioin
  3. http://stackoverflow.com/questions/426230/what-is-the-ld-preload-trick
  4. http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
  5. https://perf.wiki.kernel.org/index.php/Tutorial

2015年3月2日 星期一

[Embedded] 在 ARM in Linux 編譯 perf

要改善系統效能,首先必須有個量測系統效能的工具,本篇紀錄在 ARM in Linux 如何手動編譯 perf 。

摘錄網路上對 perf 的說明如下:

perf (sometimes called "Perf Events"or perf tools, originally "Performance Counters for Linux", PCL) is a performance analyzing tool in Linux, available from Linux kernel version 2.6.31.

it can instrument CPU performance counters, tracepoints, kprobes, and uprobes (dynamic tracing). It is capable of lightweight profiling. It is also included in the Linux kernel, under tools/perf, and is frequently updated and enhanced.

perf 的使用範例可以參考 IBM提供的文章,

2015年2月20日 星期五

[Embedded] 一個練習組合語言的小遊戲 -- Defusing bomb (part 2)

遊戲說明請參考  http://wiki.csie.ncku.edu.tw/embedded/Lab34。


以下記錄自己的解答方式。本篇僅紀錄 part2 的解法,透過此練習可學得如何利用 stack overflow 來執行 shellcode。

[Embedded] 一個練習組合語言的小遊戲 -- Defusing bomb (part 1)

此遊戲的設計目的是要讓使用者學會利用 gdb 與 objdump 分析執行檔,並學習 hack 程式!!!! 遊戲說明請參考  http://wiki.csie.ncku.edu.tw/embedded/Lab34。

以下記錄自己的解答方式。本篇僅紀錄 part1 的解法,簡單來說就是使用gdb找出正確輸入值,避免程式進入 explode_bomb()。

2015年2月7日 星期六

[Embedded] GDB script -- generate a basic report per core file

wikibook 針對 core dump 使用,提供了幾個有用的 script,其中有個自動產生報表的方式對我幫助很大。摘錄如下:


#!/bin/bash

#
# A script to extract core-file informations
#


if [ $# -ne 1 ]
then
echo "Usage: `basename $0` "
exit -1
else
binimg=$1
fi


# Today and yesterdays cores
cores=`find . -name '*.core' -mtime -1`

#cores=`find . -name '*.core'`


for core in $cores
do
gdblogfile="$core-gdb.log"
rm $gdblogfile

bininfo=`ls -l $binimg`
coreinfo=`ls -l $core`

gdb -batch \
-ex "set logging file $gdblogfile" \
-ex "set logging on" \
-ex "set pagination off" \
-ex "printf \"**\n** Process info for $binimg - $core \n** Generated `date`\n\"" \
-ex "printf \"**\n** $bininfo \n** $coreinfo\n**\n\"" \
-ex "file $binimg" \
-ex "core-file $core" \
-ex "bt" \
-ex "info proc" \
-ex "printf \"*\n* Libraries \n*\n\"" \
-ex "info sharedlib" \
-ex "printf \"*\n* Memory map \n*\n\"" \
-ex "info target" \
-ex "printf \"*\n* Registers \n*\n\"" \
-ex "info registers" \
-ex "printf \"*\n* Current instructions \n*\n\"" -ex "x/16i \$pc" \
-ex "printf \"*\n* Threads (full) \n*\n\"" \
-ex "info threads" \
-ex "bt" \
-ex "thread apply all bt full" \
-ex "printf \"*\n* Threads (basic) \n*\n\"" \
-ex "info threads" \
-ex "thread apply all bt" \
-ex "printf \"*\n* Done \n*\n\"" \
-ex "quit"
done

Reference:
http://en.m.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Core_files

2015年2月6日 星期五

[Embedded] GDB script -- check stack when stack corrupt

若使用 gdb 檢查 core dump 時,發現 stack corrupt,此時該如何看到正確的 stack trace 呢?

問題情況舉例如下:(使用 stackoverflow 的例子做說明)

Program received signal SIGSEGV, Segmentation fault.
0x00000002 in ?? ()
(gdb) bt
#0  0x00000002 in ?? ()
#1  0x00000001 in ?? ()
#2  0xbffff284 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

問題解決方式:(假設系統架構為 Linux 32-bit x86)

1. 首先必須先大概了解 Linux 作業系統內的虛擬記憶體配置
例如:
stack 會位於 0xBFxxxxxx 附近
text (程式碼) 會從 0x08048000 開始增加
因此 0xbffff284可能是正確的 stack位址,而 0x00000001 與 0x00000002 並非正確的 stack 位址,此時 stack 已經亂掉。
若對於 stack 使用有疑問,可以直接參考此範例。 

2. 以上述的錯誤位址為例,這個問題有可能因為呼叫function 時,指向了錯誤的 function pointer。
An indirect call instruction just pushes the PC after the call onto the stack and then sets the PC to the target value (bogus in this case), so if this is what happened, you can easily undo it by manually popping the PC off the stack. In 32-bit x86 code you just do:

(gdb) set $pc = *(void **)$sp
(gdb) set $sp = $sp + 4

3. 另外一個可能是正確的 stack 被覆蓋了。此時基本處理原則是將整個 stack 都尋找一遍,直到找到對應的程式進入點為止 (例如:main())。
例如: (gdb) x/256wa $sp 
其基本原理為從目前的 sp register 開始,每隔一個 word(4bytes),印出對應的位址,若有對應的 symbol 會一併列印,持續尋找 256 words。

4. 若想要將 stack 狀態寫入檔案,可以參考 Loda's blog 的 GDB 筆記,其基本原理與 x/256wa $sp 相同,不過產生出的 log 較方便閱讀。摘錄如下:
file executable_file_build_with_debug_flag
set solib-search-path builtin-symbol-library-file-path
set solib-absolute-prefix builtin-symbol-library-filepath-prefix
core core_dump_file
set print symbol-filename on
set logging file stack-out.txt
set logging on
set $stack_addr=$sp
printf "Start to decode tack\n"
set $i=0
while($i<256 br=""> printf "i:%ld stack_addr:%xh\n",$i,$stack_addr
print /a *(int *) $stack_addr
set $stack_addr = $stack_addr +4
set $i = $i + 1
end
printf "End\n"
set logging off

Reference:

[Embedded] GDB script -- check deadlock caused by mutex

Gdb scripts can be used to fix bugs easily. So I collect some gdb script here as reference.
The first script is used to find the deadlock caused by mutex misuse.

Reference : Debug Hacks

1. For example: debug.cmd
set pagination offset logging file debug.log
set logging overwrite
set logging on
start
set $addr1 = pthread_mutex_lock
set $addr2 = pthread_mutex_unlock
b *$addr1
b *$addr2
while 1
   c
   if $pc != $addr1 & $pc != $addr2
      quit
   end
   printf "## addr : %08x\n", *(int *)($esp+4)
   bt
end 
NOTE: when you press ctrl+c, this script will quit.

2. Usage
$ gdb ./a.out -x debug.cmd

2015年1月24日 星期六

[Embedded] Why no core dump after segmentation fault?

1. Follow below command to set core dump generated in embedded Linux.
$ ulimit -c 1024
$ echo '/tmp/core_%e.%p' | tee /proc/sys/kernel/core_pattern

2. Why no core dump?
  • no write access to the directory 
  • use "ls" to check
  • the program changes the working directory 
  • how to check??
  • look for the core in other places too 
  • use "sysctl -a | grep core_pattern" to check
  • disk is full 
  • use "df ." to check
  • most Unix systems do not allow a setuid process to dump core 
  • use "cat /proc/sys/fs/suid_dumpable" to check,  
  • use "echo 1 > /proc/sys/fs/suid_dumpable" to change setting 
  • ulimit is set in one shell and the program is started in a different shell or environment
  • check /proc/pid/environ for current shell
  • note that only the program executed after "ulimit -c 1024" can generate core

3. We can use "kill -ABRT  pid_of_process" to generate core manually.

4. Check /proc/pid/limits for system limit
Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            8388608              unlimited            bytes
Max core file size        0                    unlimited            bytesMax resident set          unlimited            unlimited            bytes
Max processes             748                  748                  processes
Max open files            1024                 1024                 files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       748                  748                  signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

Reference:
  1. http://stackoverflow.com/questions/15272817/segmentation-fault-no-core-dump
  2. http://www.idimmu.net/2013/06/21/enable-linux-core-dump/
  3. http://www.gnu.org/software/bash/manual/bashref.html#Bourne-Shell-Builtins
  4. http://blog.csdn.net/pro_or_gram/article/details/15813879
  5. http://linuxxperts.com/enabling-core-dumps-in-embedded-systems/
  6. http://tieba.baidu.com/p/2365639005

2015年1月18日 星期日

[Embedded] Ubuntu的核心編譯

Below is the procedures to compile a linux kernel for ubuntu 

1.  get kernel source code 
$ sudo apt-get install linux-source
$ cp /usr/src/linux-source-3.13.0.tar.bz2 ~/ubuntu
$ cd ~/ubuntu
$ tar jxvf linux-source-3.13.0.tar.bz2

2. compile kernel
$ cd linux-source-3.13.0
$ make menuconfig
$ make

3. install new kernel
$ make modules_install
$ make install
$ update-initramfs -c -k

5. make sure kernel is build correctly
$ sudo ls /boot/*

6. check current kernel versuib
$ uname -r
// The original version is The new version is linux-source-3.13.0

7. After reboot
$ uname -r
// The new version is linux-source-3.13.0

2012年5月6日 星期日

C語言測試 想成為嵌入式程序員應知道的0x10個基本問題


C語言測試 想成為嵌入式程序員應知道的0x10個基本問題

原文出處 A 'C' Test: The 0x10 Best Questions for Would-be Embedded
Programmers: http://www.embedded.com/2000/0005/0005feat2.htm

以下是網路上找到中文版,作者不詳。

==============================================



C語言測試是徵選嵌入式系統程式員過程中必須而且有效的方法。這些年我既參加也組織
了許多這種測試,在這過程中我意識到這些測試能為面試者和被面試者提供許多有用訊息
,此外,撇開面試的壓力不談,這種測試也是相當有趣的。

從被面試者的角度來講,你能瞭解許多關於出題者或監考者的情況。這個測試只是出題者
出某個字符的ASCII值。這些問題著重考察你的系統調用(invoke)和記憶體分發策略方面
的能力嗎?這反映出出題者也許花時間在微處理機上而不在嵌入式系統上。

如果上述任何問題的答案是「是」的話,那麼我知道我得認真考慮我是否應該去做這份工
作。

從面試者的角度來講,一個測試也許能從多方面揭示應試者的素質。最基本的,你能瞭解
應試者C語言的水準。不管怎麼樣,看一下這人如何回答他不會的問題也是滿有趣。應試
者是以好的直覺做出明智的選擇,還是只是瞎蒙呢?當應試者在某個問題上卡住時是找藉
口呢,還是表現出對問題的真正的好奇心,把這看成學習的機會呢?我發現這些訊息與他
們的測試成績一樣有用。

有了這些想法,我決定出一些真正針對嵌入式系統的考題,希望這些令人頭痛的考題能給
正在謀職的人一點幫住。這些問題都是我這些年實際碰到的。其中有些題很難,但它們應
該都能給你一點啟發。

2012年1月10日 星期二

[Embedded] ARM ToolChain 建立 (OpenSource)


原本想採用 ARM官方的開發工具Keli進行開發,但因為成本考量因素,所以改成採用open source的方式。

以下介紹開發環境安裝步驟

1      安裝 Minimalist GNU for Windows
此工具會在Windows系統下建立一個 GNU的開發環境,而且可以直接與Windows的檔案系統溝通。預設便已經有gcc 可以編譯程式。安裝時記得要勾選 MSYS。

2012年1月9日 星期一

[Embedded] ARM Coretex M3 程式寫作注意事項


最近需要在 ARM Cortex M3 上開發一個安全監控系統,茲將程式寫作時需要注意的事項整理如下:

l  區域變數(Local Variable)
Ø   若使用較大的變數定義(long),會使用運算較慢的指令集,造成整體效能較慢,但不會增加çode size。
Ø   但使用較小的變數定義(),則需要多餘的指令作變數轉換,會增加code size。
Ø   編譯器有個最佳化選項 ”all-in-register locals”,會將local變數放在register上(Cortex M3共有13個 32-bit general-purpose registers),當暫存器用完的時候,local變數才會放入到stack中。如此可以加速存取local 變數的時間。
建議:使用 int, unsigned int, 和 long,而不要使用 short。

2011年12月15日 星期四

[Embedded] Bootloader


Bootloader

一般的開機流程,主要可分成三個階段:
1.      各家CPU廠商會指定CPU一開始執行的程式位址,例如:ARM為0x00000000, MIPS為0xBFC00000,而ARM Cortex M3則根據0x00000004所設定的重置向量來決定位址,一旦CPU上電,CPU就會到對應的位址讀取需要執行的程式,此程式即bootloader。
2.      由開發板的廠商提供各種初始化周邊的程式,進行初始化流程。
3.      載入作業系統。