2014년 1월 29일 수요일

포인터와 배열은 어떻게 다른가 in assembly level

포인터와 배열은 다들 알다시피 비슷하지만 다른데, 어셈블리 레벨에서 보면 더욱 자세히 와닿을 수 있다.

다음은 간단하게 배열과 포인터를 각각 사용하는 c 코드와 그로부터 만들어진 어셈블리 코드이다.


arr.s의 6, 7라인. 그리고 22라인을 보자.
어레이의 경우는 리터럴의 시작주소가 곧 자신의 위치이다.
따라서 접근을 할 때, $a와 같이 해당 심볼의 위치를 바로 가져온다.

ptr.s에서는 4,5,10,11라인. 그리고 26라인을 보자.
반면, 포인터는 리터럴의 시작주소를 값으로 가진다.
따라서 접근 시, a(%rip)와 같이, rip relative 방식으로 해당 변수의 '값'을 가져온다.

2014년 1월 28일 화요일

How to upload a kernel module on Android emulator


Because Android system use linux as it's kernel, you can run your code in kernel mode by make and load a kernel module on Android.

This post simply explain how to build and load a kernel module on Android emulator.

Name of virtual device for default Android emulator is goldfish. So, in this post, I will call the kernel for Android emulator as goldfish kernel.

0. Environment
Development device / software version I used for this post is:

  • ubuntu 12.04 desktop 64bit
  • git 1.7.9.5
  • AOSP master branch synced someday between 4.2.1_r1 and 4.2.2


1. Build & Use goldfish kernel
goldfish kernel doesn't support module in default. So, you should modify the setting to support module, build again with the setting, and use the rebuilt kernel.

1.1. Get kernel source code for Android emulator
$ git clone https://android.googlesource.com/kernel/goldfish
$ cd goldfish
$ git checkout android-goldfish-2.6.29
(You can pick which branch to checkout as you want. You can see which branch is available using $ git branch -r command)

1.2. Get prebuilt project
For cross-compile, you should get AOSP's prebuilt project.
$ git clone https://android.googlesource.com/platform/prebuilt

1.3. kernel build configuration setting
You can set linux kernel build setting as you want. The setting information is saved as .config file in source code directory. But, the source code you got in above step have no .config file.
Make default goldfish kernel build configuration file with the command below:
$ make goldfish_defconfig

Now, you can see .config file. Or, you can get the configuration of already running emulator with command below.
$ adb pull /proc/config.gz
$ gunzip config.gz
$ mv config .config

1.4. Modify configuration to support module
Open .config file you generated and add next lines:
CONFIG_MODULES=y
CONFIG_MODULES_FORCE_LOAD=y
CONFIG_MODULES_UNLOAD=y
CONFIG_MODULES_FORCE_UNLOAD=y

If you don't set CONFIG_MODULE_UNLOAD, you can't unload moudle after loading. Be careful.

1.5. Build goldfish kernel
You can just follow s.android.com's same contents. In summary,
$ ARCH=arm CROSS_COMPILE=<path to prebuilt we downloaded above>/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi- make -j2

The <path to prebuild we downloaded above> should be alternated with the path to prebuild you got from 1.2 section.
After build process, You can see the kernel image, zImage file.

1.6. Use the built kernel with emulator
You can specify which kernel the emulator will use with next command:
$ emulator -kernel <path of kernel image>
-show-kernel and -verbose option may be helpful in some way.

2. Build Android kernel module
Now, let's code and build kernel module for Android.
2.1. Source code for kernel module
Make simple file like below in name android_module.c

I will not explain about how the code works precisely in this post because it's not this post's object.
Simply, the source code will print "Hello android kernel..." when loaded on, "Goodbye android kernel..." message when it unloaded from kernel on kernel log.
You may change the content of source code as you want.

2.2. Write Makefile for the kernel module build process
Write Makefile with content below:
-C option at 4, 7line should point the path to kernel source code.


2.3. Build kernel module
Just set ARCH, CROSS_COMPILE environmental variable and do make. It's essentially same with kernel compile command.
$ ARCH=arm CROSS_COMPILE=<path to prebuilt we downloaded above>/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi- make

If build success, you can see android_module.ko file generated.

3. Load kernel module
$ adb push android_module.ko /data/
$ adb shell
(Now, you are on Android's shell)
# insmod /data/android_module.ko

You can see the message Hello android kernel... on kernel log by using command like dmesg.

4. Unload kernel module
$ adb shell
# rmmod android_module

You can see the message Goodbye android kernel... on kernel log by using command like dmesg, too.


* You may encounter vermagic problem during module loading on some case.
In the case, article below may be helpful.
http://dry-kiss.blogspot.kr/2013/07/android-linux-module-vermagic.html


References:
http://linuxclues.blogspot.kr/2010/05/build-compile-linux-kernel-android.html
http://stackoverflow.com/questions/6282669/how-do-you-create-a-loadable-kernel-module-for-android
http://s.android.com/

Make complex touch event on Android using monkeyrunner


You can control Android device simply using monkeyrunner.
But, because it supports only simple DRAG command which just drag from one point to other point in specific speed, users couldn't reproduce real people's complex(e.g., drawing complex picture or remove app icon from home screen) touch event.

So, I modified monkeyrunner to provide MOVE event and contributed the code to AOSP. It merged soon.
(https://android-review.googlesource.com/#/c/50991/)

After that, one day, one guy asked about how the feature can be used on stackoverflow and sent mail about that to me.
(http://stackoverflow.com/questions/18161416/android-monkey-runner-touch-with-move)

So, I made and shared a simple example code for that question. I think it would be better to share it here, too.

Just use the type MOVE like DOWN, UP as argument inside touch function call.
Hope it can be helpful to someone ;)

How to build / install linux kernel on Debian based distributions(e.g., Ubuntu) in deb format

On Debian based distribution system like Ubuntu, you can build linux kernel in deb format. It would be easier to install / redistribute the kernel.

Install Required Package

$ sudo apt-get install kernel-package

Get Linux Kernel Source Code

$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.13.tar.xz
$ tar -xJf linux-3.13.tar.xz

Set Build Configuration

$ cp /boot/config-blahblah ./.config
$ make oldconfig

Build in deb Format

$ fakeroot make-kpkg --initrd -j 3 --revision 3.13.sjpark kernel-image

Install The Kernel

$ sudo dpkg -i ../linux-image-3.13.0+_3.13.sjpark_amd64.deb
$ sudo shutdown -r now
$ uname -r

2014년 1월 26일 일요일

Debian 계열(우분투 등)에서 deb로 커널 빌드

우분투 등의 debian 계열 배포본에서는 커널도 deb로 빌드, 간편하게 설치 / 재배포 할 수 있다.

필요 패키지 설치

$ sudo apt-get install kernel-package

커널 소스코드 다운로드

$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.13.tar.xz
$ tar -xJf linux-3.13.tar.xz

빌드 configuration 설정

$ cp /boot/config-blahblah ./.config
$ make oldconfig

deb로 빌드

$ fakeroot make-kpkg --initrd -j 3 --revision 3.13.sjpark kernel-image

설치

$ sudo dpkg -i ../linux-image-3.13.0+_3.13.sjpark_amd64.deb
$ sudo shutdown -r now
$ uname -r

2014년 1월 6일 월요일

우분투에서 SRPM(Source RPM) 수정하기

0. RPM, Source RPM

RPM은 다들 알다시피 Redhat Package Manager의 약자로, 자신이 만든 소프트웨어를 배포하기 편리한 하나의 패키지로 만드는데 사용되는 시스템이며, 그렇게 만들어진 패키지를 rpm 또는 rpm 파일이라 한다.
독점 소프트웨어에서는 배포하는 패키지라면 빌드 완료된 바이너리로만 구성되어 있는 경우가 대부분이지만, 오픈소스 소프트웨어에서는 배포 패키지가 꼭 바이너리여야 할 이유가 없다. 패키징만 잘 되어 있어 주고 받기 편하고 사용자가 어느 시스템을 사용하든 그 소프트웨어를 쉽게 설치할 수 있으면 땡이다.
그리고, 어떤 면에서는 빌드가 끝난 바이너리보다 소스코드로 배포하는게 더 나은 경우가 존재한다.
따라서, RPM은 빌드가 끝난 바이너리를 패키징해서 만들수도, 소스코드를 담고 빌드 방법을 함께 담아서 패키지로 만들 수도 있다.
각각을 Binary RPM, Source RPM 이라고 부르기도 한다.

1. RPM을 수정해야 하는 경우

많은 사용자가 쉽게 사용할 수 있도록 배포자는 혼신의 노력을 기울여 패키지를 만들었겠지만, 실제 패키지를 사용해보면 문제가 발생하는 경우가 많다.
문제를 발견해서 수정해 원저자에게 패치를 보내주는게 오픈소스 소프트웨어의 좋은 경우겠지만, 때로는 원저자가 더이상 해당 프로젝트에 관심을 잃은 경우가 있고, 또는 당장의 빠른 수정이 필요한 경우가 있다.
SRPM의 경우는 특히나 소스코드를 볼 수 있으므로 자신이 수정해서 당장의 문제를 해결하는 것이 가능하다.

본 글에서는 우분투 환경에서 patch를 만들어 srpm을 수정하는 방법을 기술한다.
테스트한 환경은 우분투 13.04 64bit server판이었다.

target.src.rpm 이라는 이름의 srpm을 수정한다고 가정한다.

2. 필요 패키지 설치

먼저 시스템에 rpm 패키지가 설치되어 있지 않다면 다음 명령으로 rpm 패키지를 설치한다. rpm은 레드햇 계열의 패키지 포맷이지만 데비안 계열인 우분투에서도 rpm 패키지를 이용해 사용할 수 있다.

$ sudo apt-get install rpm

해당 패키지는 rpm을 단계별로 설치할 수 있는 rpm과, 새로이 RPM 파일을 만들 수 있는 rpmbuild다른 명령을 제공한다. 이 글에선 rpm을 이용해 코드를 풀고, 이 코드를 수정 후, 수정된 내용으로 rpmbuild를 이용해 새로인 SRPM을 만드는 식으로 수정된 SRPM을 얻을 것이다.

3. SRPM 풀기

rpm 을 이용해 srpm을 단계별로 설치할 수 있으며, 이 단계는 간략히 소스코드를 꺼내고, 빌드하고, 설치하고, 하는 단계로 이루어진다. 따라서 꺼내는 단계까지만 설치를 진행하면 우리가 보고 싶은 소스코드를 볼 수 있다. 아래 명령을 통해 소스코드를 꺼내는 단계까지만 진행할 수 있으며, 소스코드를 위치시킬 경로는 _topdir로 설정할 수 있다. 아래 명령의 /path/to/extract 는 자신이 편한 디렉토리 경로로 대체하자.

$ rpm --define ‘_topdir /path/to/extract’ -i target.src.rpm

이제 /path/to/extract에 가보면 SPECS와 SOURCE 디렉토리가 있고, 각 디렉토리 아래에는 각각 spec 파일과 압축되거나 한 형태의 소스코드가 있다.
하지만 아직 소스코드는 압축된 상태이다. 그냥 압축 해제 프로그램으로 압축을 풀지 말고, 다음의 과정을 진행하자.


4. 빌드 준비

spec 파일은 빌드 준비 / 실행 / 정리 등의 과정을 Makefile처럼 정리해 뒀고, 보통 prepare 과정을 통해 SOURCE 디렉토리 아래 소스코드를 BUILD 디렉토리 아래로 옮기고, 소스코드가 압축되어 있다면 압축을 푸는 식으로 빌드 준비를 한다. 다음의 커맨드로 이를 행한다.

$ cd /path/to/extract/SPECS
$ rpmbuild --define ‘_topdir /path/to/extract’ -bp target.spec


target.spec은 SPECS 디렉토리 아래 존재하는 spec 확장명의 파일명을 입력한다.

5. 코드 수정 & 패치 작성

이제 코드에 수정을 가하고 이를 바탕으로 패치를 만들어 SOURCE 디렉토리로 이동시켜야 한다. 오리지널 코드와 수정한 코드를 둘 다 가지고 있어야 그 차이로 변경내역을 나타내는 패치로 만들어야 하므로, 다음과 같이 오리지널 코드를 보존해 둔 상태로 코드를 수정한다.
명령어의 existing_dir은 실제 존재하는 소스코드 디렉토리의 이름으로 대체하자.

$ cd /path/to/extract/BUILD
$ cp -R ./existing_dir ./extracting_dir.orig


본인에게 편한 방법으로 /path/to/extract/BUILD/existing_dir 아래의 코드에 수정을 가하고 나서 다음 명령을 이용해 패치를 만들고 SOURCES 디렉토리 아래로 옮긴다. 역시 name_of_patch.patch는 본인이 원하는 패치 파일 이름으로 적당히 대체를.


$ diff -Npru existing_dir.orig/ existing_dir > name_of_patch.patch
$ mv name_of_patch.patch /path/to/extract/SOURCES/


6. srpm 설치 시 patch를 적용하도록 spec 파일 수정

이제 해당 srpm을 설치 시 앞의 과정에서 만든 패치를 적용하게 해야 한다. specs 파일을 수정하는 것으로 그렇게 할 수 있다.
Source 항목 아래 Patch0 라는 항목을 만들어 앞서 만든 name_of_patch.patch를 적어주고, %setup 아래 %patch0 -p1이라는 항목을 넣어 해당 patch를 사용함을 알린다.


예:
Source0: %{name}-%{version}-%{release}.tar.gz                                   
Patch0: for_ubuntu13.04_sjpark.patch                                            
Prefix: /usr                                                                    
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root                       
Requires(post): /sbin/ldconfig                                                  
Requires(postun): /sbin/ldconfig                                                
Conflicts: infinipath-libs                                                      
                                                                                
%package devel                                                                  
Summary: Development files for QLogic PSM                                       
Group: System Environment/Development                                           
Requires: %{name} = %{version}-%{release}                                       
Requires(post): /sbin/ldconfig                                                  
Requires(postun): /sbin/ldconfig                                                
Conflicts: infinipath-devel                                                     
                                                                                
%description                                                                    
The PSM Messaging API, or PSM API, is QLogic's low-level                        
user-level communications interface for the Truescale                           
family of products. PSM users are enabled with mechanisms                       
necessary to implement higher level communications                              
interfaces in parallel environments.                                            
                                                                                
%description devel                                                              
Development files for the libpsm_infinipath library                             
                                                                                
%prep                                                                           
%setup -q -n infinipath-psm-%{version}-%{release}                               
%patch0 -p1           

7. 수정된 RPM 빌드

이제 끝. 마지막으로 우리가 원하는 SRPM 또는 RPM을 얻기 위해 다음 명령을 날려준다.

$ rpmbuild --define '_topdir /path/to/extract' -ba target.spec


이제 RPMS 디렉토리 아래에 rpm이, SRPMS 디렉토리 아래에 srpm 파일이 존재할 것이다.


번외: 현 디렉토리의 모든 SRPM을 4번 단계까지 진행하는 코드

이상의 내용을 바탕으로 python으로 간략히 현 디렉토리의 모든 SRPM을 4번 단계까지, 즉 코드를 볼 수 있는 수준까지 진행하는 스크립트를 짜봤다.
https://gist.github.com/sjp38/7095984


참고 자료: