안드로이드 프레임워크

mydroid/build/core/version_defaults.mk 열어보면

 39 ifeq "" "$(PLATFORM_VERSION)"
 40   # This is the canonical definition of the platform version,
 41   # which is the version that we reveal to the end user.
 42   # Update this value when the platform version changes (rather
 43   # than overriding it somewhere else).  Can be an arbitrary string.
 44   PLATFORM_VERSION := 2.3.5
 45 endif


커널 버전

kernel/android-2.6.35/Makefile 열어보면

1 VERSION = 2
2 PATCHLEVEL = 6
3 SUBLEVEL = 35
4 EXTRAVERSION = .7+
5 NAME = Yokohama

출처 : http://www.androidpub.com/3715

전체 소스를 
http://source.android.com/download 에서 하라는데로 다운로드 받고 한번 빌드하는 것까지는 다들 쉽게 따라하셨을 것이라 생각합니다. 그 이후에 특정부분만 다시 빌드하고 싶을 때는 다시 make를 할 필요없이 mmm이라는 커맨드를 사용하면 됩니다. 

$. build/envsetup.sh
을 실행한 후

$ mmm packages/apps/Contacts
와 같이 시행하면 Contacts부분만 다시 빌드됩니다. Android.mk가 존재하는 Path만 적용할 수 있습니다.

$ make snod
를 실행하면 위에서 빌드한 Contacts를 적용한 system.img 를 다시 빠르게 생성합니다.

그리고 한글등이 들어갈 때 utf8 인코딩을 쓰게는데 안드로이드 플랫폼 소스 빌드시에 javac가 ascii 인코딩으로 설정되어있습니다. 

build/core/definitions.mk 에서 -encoding ascii 를 -encoding utf8로 바꿔주면 됩니다. utf8 소스도 사용할 수 있습니다. 

그리고 mmm과 별도로
$make sdk
를 통해 SDK를 만들 수 있습니다.


플랫폼은 왠만하면 안보려고 했는데 어플리케이션 개발하는 입장에서도 가끔씩 빌드하고 고쳐서 써야하는 부분이 있어서 팁을 정리해봅니다. 
안드로이드는 SD Card를 FAT32 까지만 인식을 한다.

문제는 FAT32  파일시스템은 단일 파일 4gb 까지만 인식을 한다.

따라서 exFAT나 NTFS or EXT2 (or3,4) 를 써야만 한다.

라이센스 문제로 exFAT NTFS는 지원하지 않고
EXT2도 공식 지원하지 않는 커널이 많다.

방법은 2가지
- NTFS  사용 : fuse 모듈을 올리면 NTFS 파일시스템을 읽을수 있다. 
- EXT2 사용 : 커널에서 ext2를 지원해야 한다. (테크라크 커널등)

어째든 둘다 자동 미디어 스캐닝은 안된다 ㅜ.ㅠ

탐색기 어플로 들어가서 재생해서 재생 가능함. or vital player 같이 파일을 탐색해서 재생하는 어플 사용.

ext2로 포맷할경우 컴터(윈도우)에서 인식은 못하므로  http://dorigom.tistory.com/340 참조하여 관련 프로그램 설치 필요.
 

참조
https://www.youtube.com/watch?v=8DHsBO55LWI


 
소스받기 : http://source.android.com/source/downloading.html
빌드하기 : http://source.android.com/source/building.html


소스 받기
repo가 업데이트 되었으므로 기존꺼 지우고 새로받아야 한다.

Downloading the Source Tree

Installing Repo

Repo is a tool that makes it easier to work with Git in the context of Android. For more information about Repo, see Version Control.

To install, initialize, and configure Repo, follow these steps:

  • Make sure you have a bin/ directory in your home directory, and that it is included in your path:

    $ mkdir ~/bin
    $ PATH=~/bin:$PATH
    
  • Download the Repo script and ensure it is executable:

    $ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo
    $ chmod a+x ~/bin/repo
    
  • The SHA-1 checksum for repo is e1fd3bef059d152edf4d0522590725d317bc637f

Initializing a Repo client

After installing Repo, set up your client to access the android source repository:

  • Create an empty directory to hold your working files. If you're using MacOS, this has to be on a case-sensitive filesystem. Give it any name you like:

    $ mkdir WORKING_DIRECTORY
    $ cd WORKING_DIRECTORY
    
  • Run repo init to bring down the latest version of Repo with all its most recent bug fixes. You must specify a URL for the manifest, which specifies where the various repositories included in the Android source will be placed within your working directory.

    $ repo init -u https://android.googlesource.com/platform/manifest
    

    To check out a branch other than "master", specify it with -b:

    $ repo init -u https://android.googlesource.com/platform/manifest -b android-4.0.1_r1
    
  • When prompted, please configure Repo with your real name and email address. To use the Gerrit code-review tool, you will need an email address that is connected with a registered Google account. Make sure this is a live address at which you can receive messages. The name that you provide here will show up in attributions for your code submissions.

A successful initialization will end with a message stating that Repo is initialized in your working directory. Your client directory should now contain a .repo directory where files such as the manifest will be kept.

Getting the files

To pull down files to your working directory from the repositories as specified in the default manifest, run

$ repo sync

The Android source files will be located in your working directory under their project names. The initial sync operation will take an hour or more to complete. For more about repo sync and other Repo commands, see Version Control.

Verifying Git Tags

Load the following public key into your GnuPG key database. The key is used to sign annotated tags that represent releases.

$ gpg --import

Copy and paste the key(s) below, then enter EOF (Ctrl-D) to end the input and process the keys.

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.2.2 (GNU/Linux)

mQGiBEnnWD4RBACt9/h4v9xnnGDou13y3dvOx6/t43LPPIxeJ8eX9WB+8LLuROSV
lFhpHawsVAcFlmi7f7jdSRF+OvtZL9ShPKdLfwBJMNkU66/TZmPewS4m782ndtw7
8tR1cXb197Ob8kOfQB3A9yk2XZ4ei4ZC3i6wVdqHLRxABdncwu5hOF9KXwCgkxMD
u4PVgChaAJzTYJ1EG+UYBIUEAJmfearb0qRAN7dEoff0FeXsEaUA6U90sEoVks0Z
wNj96SA8BL+a1OoEUUfpMhiHyLuQSftxisJxTh+2QclzDviDyaTrkANjdYY7p2cq
/HMdOY7LJlHaqtXmZxXjjtw5Uc2QG8UY8aziU3IE9nTjSwCXeJnuyvoizl9/I1S5
jU5SA/9WwIps4SC84ielIXiGWEqq6i6/sk4I9q1YemZF2XVVKnmI1F4iCMtNKsR4
MGSa1gA8s4iQbsKNWPgp7M3a51JCVCu6l/8zTpA+uUGapw4tWCp4o0dpIvDPBEa9
b/aF/ygcR8mh5hgUfpF9IpXdknOsbKCvM9lSSfRciETykZc4wrRCVGhlIEFuZHJv
aWQgT3BlbiBTb3VyY2UgUHJvamVjdCA8aW5pdGlhbC1jb250cmlidXRpb25AYW5k
cm9pZC5jb20+iGAEExECACAFAknnWD4CGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIX
gAAKCRDorT+BmrEOeNr+AJ42Xy6tEW7r3KzrJxnRX8mij9z8tgCdFfQYiHpYngkI
2t09Ed+9Bm4gmEO5Ag0ESedYRBAIAKVW1JcMBWvV/0Bo9WiByJ9WJ5swMN36/vAl
QN4mWRhfzDOk/Rosdb0csAO/l8Kz0gKQPOfObtyYjvI8JMC3rmi+LIvSUT9806Up
hisyEmmHv6U8gUb/xHLIanXGxwhYzjgeuAXVCsv+EvoPIHbY4L/KvP5x+oCJIDbk
C2b1TvVk9PryzmE4BPIQL/NtgR1oLWm/uWR9zRUFtBnE411aMAN3qnAHBBMZzKMX
LWBGWE0znfRrnczI5p49i2YZJAjyX1P2WzmScK49CV82dzLo71MnrF6fj+Udtb5+
OgTg7Cow+8PRaTkJEW5Y2JIZpnRUq0CYxAmHYX79EMKHDSThf/8AAwUIAJPWsB/M
pK+KMs/s3r6nJrnYLTfdZhtmQXimpoDMJg1zxmL8UfNUKiQZ6esoAWtDgpqt7Y7s
KZ8laHRARonte394hidZzM5nb6hQvpPjt2OlPRsyqVxw4c/KsjADtAuKW9/d8phb
N8bTyOJo856qg4oOEzKG9eeF7oaZTYBy33BTL0408sEBxiMior6b8LrZrAhkqDjA
vUXRwm/fFKgpsOysxC6xi553CxBUCH2omNV6Ka1LNMwzSp9ILz8jEGqmUtkBszwo
G1S8fXgE0Lq3cdDM/GJ4QXP/p6LiwNF99faDMTV3+2SAOGvytOX6KjKVzKOSsfJQ
hN0DlsIw8hqJc0WISQQYEQIACQUCSedYRAIbDAAKCRDorT+BmrEOeCUOAJ9qmR0l
EXzeoxcdoafxqf6gZlJZlACgkWF7wi2YLW3Oa+jv2QSTlrx4KLM=
=Wi5D
-----END PGP PUBLIC KEY BLOCK-----

After importing the keys, you can verify any tag with

$ git tag -v TAG_NAME


 

Building the System

The basic sequence of build commands is as follows:

Initialize

Initialize the environment with the envsetup.sh script. Note that replacing "source" with a single dot saves a few characters, and the short form is more commonly used in documentation.

$ source build/envsetup.sh

or

$ . build/envsetup.sh

Choose a Target

Choose which target to build with lunch. The exact configuration can be passed as an argument, e.g.

$ lunch full-eng

The example above refers to a complete build for the emulator, with all debugging enabled.

If run with no arguments lunch will prompt you to choose a target from the menu.

All build targets take the form BUILD-BUILDTYPE, where the BUILD is a codename referring to the particular feature combination:

Build nameDeviceNotes
full emulator fully configured with all languages, apps, input methods
full_maguro maguro full build running on Galaxy Nexus GSM/HSPA+ ("maguro")
full_panda panda full build running on PandaBoard ("panda")

and the BUILDTYPE is one of the following:

BuildtypeUse
user limited access; suited for production
userdebug like "user" but with root access and debuggability; preferred for debugging
eng development configuration with additional debugging tools

For more information about building for and running on actual hardware, see Building for devices

Build the Code

Build everything with make. GNU make can handle parallel tasks with a -jN argument, and it's common to use a number of tasks N that's between 1 and 2 times the number of hardware threads on the computer being used for the build. E.g. on a dual-E5520 machine (2 CPUs, 4 cores per CPU, 2 threads per core), the fastest builds are made with commands between make -j16 and make -j32.

$ make -j4

Run It!

You can either run your build on an emulator or flash it on a device. Please note that you have already selected your build target with lunch, and it is unlikely at best to run on a different target than it was built for.

Flash a Device

To flash a device, you will need to use fastboot, which should be included in your path after a successful build. Place the device in fastboot mode either manually by holding the appropriate key combination at boot, or from the shell with

$ adb reboot bootloader

Once the device is in fastboot mode, run

$ fastboot flashall -w

The -w option wipes the /data partition on the device; this is useful for your first time flashing a particular device, but is otherwise unnecessary.

For more information about building for and running on actual hardware, see Building for devices

Emulate an Android Device

The emulator is added to your path automatically by the build process. To run the emulator, type

$ emulator

Using ccache

ccache is a compiler cache for C and C++ that can help make builds faster. In the root of the source tree, do the following:

$ export USE_CCACHE=1
$ export CCACHE_DIR=/<path_of_your_choice>/.ccache
$ prebuilt/linux-x86/ccache/ccache -M 20G

You can watch ccache being used by doing the following:

$ watch -n1 -d prebuilt/linux-x86/ccache/ccache -s

On OSX, you should replace linux-x86 with darwin-x86.

Troubleshooting Common Build Errors

Wrong Java Version

If you are attempting to build froyo or earlier with Java 1.6, or gingerbread or later with Java 1.5, make will abort with a message such as

************************************************************
You are attempting to build with the incorrect version
of java.

Your version is: WRONG_VERSION.
The correct version is: RIGHT_VERSION.

Please follow the machine setup instructions at
    http://source.android.com/download
************************************************************

This may be caused by

  • failing to install the correct JDK as specified on the Initializing page. Building Android requires Sun JDK 5 or 6 depending on which release you are building.

  • another JDK that you previously installed appearing in your path. You can remove the offending JDK from your path with:

    $ export PATH=${PATH/\/path\/to\/jdk\/dir:/}
    

Python Version 3

Repo is built on particular functionality from Python 2.x and is unfortunately incompatible with Python 3. In order to use repo, please install Python 2.x:

$ apt-get install python

Gmake Version 3.82

There is a bug in make version 3.82 on Mac OS that prevents building Android.

TODO: what the error looks like with GNU make 3.82 on older builds that don't explicitly detect it.

Follow the instructions on the Initializing page for reverting GNU make from 3.82 to 3.81.

Case Insensitive Filesystem

If you are building on an HFS filesystem on Mac OS X, you may encounter an error such as

************************************************************
You are building on a case-insensitive filesystem.
Please move your source tree to a case-sensitive filesystem.
************************************************************

Please follow the instructions on the Initializing page for creating a case-sensitive disk image.

No USB Permission

On most Linux systems, unprivileged users cannot access USB ports by default. If you see a permission denied error, follow the instructions on the Initializing page for configuring USB access.

If adb was already running and cannot connect to the device after getting those rules set up, it can be killed with adb kill-server. That will cause adb to restart with the new configuration.

  • Favicon of http://www.moncleroutletespain.com/ BlogIcon moncler 2013.01.04 12:37

    Un millier de coptes de France s'est réuni vendredi devant la cathédrale Notre-Dame de Paris pour affirmer leur solidarité à leurs coreligionnaires égyptiens, http://www.moncleroutletespain.com/ http://www.moncleroutletespain.com/, a constaté un journaliste de l'AFP, http://www.moncleroutletespain.com/ moncler chaquetas.Related articles:


    http://10900102.tistory.com/314 http://10900102.tistory.com/314

    http://luckyducky.co.kr/109 http://luckyducky.co.kr/109

  • Favicon of http://www.moncleroutletespain.com/ BlogIcon moncler outlet 2013.01.05 18:04

    La première émission de l'Union européenne destinée à financer le plan d'aide à l'Irlande a rencontré mercredi une très forte demande, http://www.moncleroutletespain.com/ moncler outlet, à hauteur de 19 milliards d'euros, http://www.moncleroutletespain.com/ moncler chaquetas, alors que seuls 5 milliards seront effectivement alloués, http://www.moncleroutletespain.com/ moncler, a indiqué la banque HSBC, http://www.moncleroutletespain.com/ moncler españa. Economie A vendre: 35, http://www.moncleroutletespain.com/ moncler online.000 euros pour un chateau, http://www.moncleroutletespain.com/ http://www.moncleroutletespain.com/...d'eau Economie La Tribune placé en procédure de sauvegardeRelated articles:


    http://bkmuzik.tistory.com/26 http://bkmuzik.tistory.com/26

    http://blueshoon.tistory.com/3 http://blueshoon.tistory.com/3

objdump 개발 개발/Android 2011. 11. 14. 18:10

출처 : http://smilk.egloos.com/486882

시작

질문은 간단하다. 리눅스는 어떻게 내가 만든 main()을 실행하나? 
이 글은 아래 간단한 C 프로그램을 예로 삼아 설명한다. 이를 "simple.c"라 하자.

main() {
return(0);
}

컴파일

 

gcc -o simple simple.c

실행파일에는 무엇이 들어있나?

실행파일에 무엇이 있는지 보기위해 "objdump" 도구를 사용하자.

objdump -f simple

simple: file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080482d0
출력은 실행파일에 대한 귀중한 정보를 알려준다.
 먼저 파일은 "ELF32" 형식이다. 둘째로 시작주소가 "0x080482d0"이다.

ELF란 무엇인가?

ELF는 Executable and Linking Format의 준말로, 유닉스 시스템에서 사용되는 여러 오브젝트파일/실행파일 형식중 하나이다. 
여기서 ELF에 대해 흥미로운 것은 ELF 헤더 형식이다. 모든 ELF 실행파일은 다음과 같은 ELF 헤더를 가진다.

typedef struct {
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Architecture */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point virtual address */
Elf32_Off e_phoff; /* Program header table file offset */
Elf32_Off e_shoff; /* Section header table file offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size in bytes */
Elf32_Half e_phentsize; /* Program header table entry size */
Elf32_Half e_phnum; /* Program header table entry count */
Elf32_Half e_shentsize; /* Section header table entry size */
Elf32_Half e_shnum; /* Section header table entry count */
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;
위 구조체에서 "e_entry" 필드는 실행파일의 시작주소이다.

주소 "0x080482d0", 즉 시작주소가 무엇인가?

답을 위해, "simple"을 역어셈블해보자. 실행파일을 역어셈블하는 도구는 많다. 여기서는 objdump를 사용한다.

objdump --disassemble simple
objdump의 출력이 조금 길기때문에 다 적지는 않겠다. 우리의 목적은 주소 0x080482d0에 무엇이 있는지 아는 것이다. 출력은 다음과 같다.
080482d0 <_start>:
80482d0: 31 ed xor %ebp,%ebp
80482d2: 5e pop %esi
80482d3: 89 e1 mov %esp,%ecx
80482d5: 83 e4 f0 and $0xfffffff0,%esp
80482d8: 50 push %eax
80482d9: 54 push %esp
80482da: 52 push %edx
80482db: 68 20 84 04 08 push $0x8048420
80482e0: 68 74 82 04 08 push $0x8048274
80482e5: 51 push %ecx
80482e6: 56 push %esi
80482e7: 68 d0 83 04 08 push $0x80483d0
80482ec: e8 cb ff ff ff call 80482bc <_init+0x48>
80482f1: f4 hlt
80482f2: 89 f6 mov %esi,%esi
시작주소에 "_start"라는 어떤 시작함수가 있는 것 같다. 하는 일은 레지스터를 지우고, 스택에 값을 몇개 푸쉬한(push) 후, 함수를 호출한다. 이 명령을 실행하면 스택플래임(stack frame)은 다음과 같이 된다.
Stack Top -------------------
0x80483d
-------------------
esi
-------------------
ecx
-------------------
0x8048274
-------------------
0x8048420
-------------------
edx
-------------------
esp
-------------------
eax
-------------------

이제 이 스택플래임에 대한 궁금증이 더 생겼다.

  1. 이 16진수 값들은 무엇인가? 
  2. _start가 호출하는 주소 80482bc에는 무엇이 있는가? 
  3. 어셈블리 명령어는 레지스터를 의미있는 값으로 초기화하지 않는 것 같다. 그러면 누가 레지스터를 초기화하나? 

 

하나씩 답을 하겠다.

Q1>16진수 값.

objdump의 역어셈블된 출력을 자세히 살펴보면 이 질문에 쉽게 답할 수 있다.

답은, 

0x80483d0 :        이는 우리가 만든 main() 함수의 주소이다.

0x8048274 :         _init 함수.

0x8048420 :        _fini 함수. _init과 _fini는 GCC가 제공하는 초기화(initialization)/종료(finalization) 함수이다.

당장은 이들을 신경쓰지마라. 기본적으로 이 16진수 값들은 함수포인터다.

Q2>주소 80482bc에 무엇이 있나?

다시 역어셈블된 출력에서 주소 80482bc를 찾자.
찾으면 다음과 같을 것이다.

80482bc: ff 25 48 95 04 08 jmp *0x8049548

여기서 *0x8049548는 포인터 연산이다.
 주소 0x8049548에 저장된 주소로 건너뛴다.


ELF와 동적링크에 대해 더 자세히

ELF를 사용하여 라이브러리에 동적으로 링크되는 실행파일을 만들 수 있다.
여기서 "동적으로 링크된다는" 말은 링크 과정이 실행시 발생함을 의미한다. 그렇지않으면 호출하는 모든 라이브러리를 포함하는 큰 실행파일을 ("정적으로 링크된" 실행파일) 만들어야 한다. 아래 명령을 실행하면,

"ldd simple"

libc.so.6 => /lib/i686/libc.so.6 (0x42000000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

simple과 동적으로 링크된 모든 라이브러리를 볼 수 있다. 동적으로 링크되는 자료와 함수는 모두 "동적 재배치 항목 (dynamic relocation entry)"을 가진다. 

개념은 대략 다음과 같다. 
  1. 우리는 링크시 동적 심볼의 실제 주소를 모른다. 실행할때가 되서야 심볼의 실제 주소를 알게된다.
  2. 동적 심볼의 실제 주소를 위해 메모리 공간을 남겨둔다. 
    로더(loader)가 실행시 이곳에 심볼의 실제 주소를 쓴다. 
  3. 프로그램은 일종의 포인터 연산을 통해 간접적으로 이 메모리 위치에 있는 동적 심볼을 보게된다. 우리의 경우 주소 80482bc에는 달랑 jump 명령어 하나가 있다.
    실행시 로더가 건너뛸 주소를 주소 0x8049548에 저장한다.
    objdump 명령어로 모든 동적 링크 항목을 볼 수 있다.
    objdump -R simple

    simple: file format elf32-i386

    DYNAMIC RELOCATION RECORDS
    OFFSET TYPE VALUE
    0804954c R_386_GLOB_DAT __gmon_start__
    08049540 R_386_JUMP_SLOT __register_frame_info
    08049544 R_386_JUMP_SLOT __deregister_frame_info
    08049548 R_386_JUMP_SLOT __libc_start_main
    여기서 주소 0x8049548은 알맞게 "jump slot"으로 나왔다. 표에 따르면 우리는 실제 __libc_start_main을 호출한다.

__libc_start_main은 무엇인가?

이제 작업은 libc에 달렸다. __libc_start_main은 libc.so.6에 있는 함수다. glibc 소스코드에서 __libc_start_main을 찾으면 함수형이 다음과 같다.

extern int BP_SYM (__libc_start_main) (int (*main) (int, char **, char **),
int argc,
char *__unbounded *__unbounded ubp_av,
void (*init) (void),
void (*fini) (void),
void (*rtld_fini) (void),
void *__unbounded stack_end)
__attribute__ ((noreturn));
(_start) 어셈블리 명령어는 아규먼트 스택을 만들고 __libc_start_main을 부른다. 
이 함수는 몇몇 자료구조와 환경변수를 만들고 초기화한 후, 우리가 만든 main()을 부른다. 
이 함수형을 가지고 스택플래임을 살펴보자. 

Stack Top     -------------------
                        0x80483d0                               main
                     ------------------- 
                        esi                                            argc
                     ------------------- 
                        ecx                                           argv 
                    ------------------- 
                        0x8048274                             _init
                     ------------------- 
                        0x8048420                             _fini
                     ------------------- 
                        edx                                         _rtlf_fini
                     ------------------- 
                        esp                                         stack_end
                     ------------------- 
                        eax                                         이것은 0이다
                     ------------------- 

이 스택플래임에 따르면, __libc_start_main()이 실행되기 전에 esi, ecx, edx, esp, eax 레지스터에 적당한 값이 채워져야 한다. 그러나 위에서 본 듯이 _start 어셈블리 명령어는 이 레지스터를 설정하지않는다. 그렇다면 누가 이 레지스터를 설정하나? 이제 한 군데가 남았다. 바로 커널이다. 
이제 세번째 질문으로 돌아가자.

Q3>커널은 무엇을 하는가?

쉘에 명령어를 입력하여 프로그램이 실행될때 리눅스에서는 다음과 같은 일이 일어난다.

  1. 쉘은 argc/argv를 가지고 커널 시스템호출 "evecve"를 부른다. 
  2. 커널 시스템호출 핸들러가 제어를 맏아 시스템호출을 처리하기 시작한다. 커널 코드에서 핸들러는 "sys_execve"이다. x86에서 사용자모드 프로그램은 아래 레지스터를 통해 필요한 파라미터를 커널에 넘긴다.
    • ebx : 프로그램명 문자열의 포인터
    • ecx : argv 배열 포인터
    • edx : 환경변수 배열 포인터.
     
  3. 일반적인 커널 시스템호출 핸들러 do_execve가 불린다. 이는 자료구조를 만들고 사용자영역에서 커널영역으로 자료를 복사한 후, 마지막으로 search_binary_handler()를 부른다. 리눅스는 a.out과 ELF와 같은 여러 실행파일 형식을 지원할 수 있다. 이를 위해 각각의 바이너리 형식을 읽어들일 수 있는 함수의 포인터를 담은 "struct linux_binfmt" 자료구조가 있다. search_binary_handler()는 적당한 핸들러를 찾아서 부른다. 이 경우 핸들러는 load_elf_binary()이다. 함수에 대해 자세히 설명하면 너무 길어지고 지루해지기 때문에 생략하겠다. 관심이 있다면 관련 서적을 참고하라. 그림은 천마디 말과 같고, 천줄의 소스코드는 (종종) 만마디 말과 같다. 함수의 요점만 설명하겠다. 함수는 먼저 파일 작업을 위해 커널 자료구조를 만들고 ELF 실행파일을 읽어들인다. 그런후 코드 크기, 자료 세그먼트 시작(data segment start), 스택 세그먼트 시작 (stack segment start) 등 커널 자료구조를 만든다. 그리고 이 프로세스에 대한 사용자모드 페이지를 할당하고, argv와 환경변수를 할당된 페이지 주소로 복사한다. 마지막으로 create_elf_tables()를 사용하여 argc, argv 포인터, 환경변수 배열 포인터를 사용자모드 스택에 푸쉬하고, start_thread()로 프로세스 실행을 시작한다. 


_start 어셈블리 명령어가 시작할때 스택플래임은 다음과 같다. 

Stack Top        -------------
                            argc
                        -------------
                            argv pointer
                        -------------
                            env pointer
                        ------------- 

그러면 어셈블리 명령어는 다음과 같이 스택에서 모든 정보를 얻을 수 있다.

pop %esi <--- argc를 얻는다
move %esp, %ecx <--- argv를 얻는다
실제로 argv 주소는 현재 스택포인터와 동일하다.
이제 실행을 시작할 준비가 끝났다.

다른 레지스터는 어떻게 설정되나?

esp는 프로그램의 스택 끝을 가리키는데 사용된다. 필요한 정보를 팝한(pop) 후, _start 함수는 스택포인터(esp) 레지스터에서 하위 4 비트를 끈다. 우리 프로그램에서 이것이 실제로 스택의 끝이므로 당연하다. edx는 일종의 프로그램 파괴자(destructor)인 rtld_fini에 사용된다. 커널은 다음 매크로로 이 레지스터를 0으로 만든다.

#define ELF_PLAT_INIT(_r) do { \
_r->ebx = 0; _r->ecx = 0; _r->edx = 0; \
_r->esi = 0; _r->edi = 0; _r->ebp = 0; \
_r->eax = 0; \
} while (0)
0은 x86 리눅스에서 그 기능을 사용하지 않음을 뜻한다.

어셈블리 명령어에 대해

이들 코드는 어디서 왔는가? 이 코드들은 GCC 코드의 일부다. 보통 이 코드에 대한 오브젝트파일을
/usr/lib/gcc-lib/i386-redhat-linux/XXX과 (XXX은 gcc 버전)
/usr/lib에서 찾을 수 있다.
파일명은 crtbegin.o,crtend.o, gcrt1.o이다.

 

요약

다음과 같은 일이 일어난다. 

  1. GCC는 crtbegin.o/crtend.o/gcrt1.o을 첨가하여 프로그램을 컴파일한다. 또, 기본적으로 다른 기본 라이브러리들도 동적으로 링크된다. 프로그램의 시작주소는 _start의 주소로 설정된다.
  2. 커널은 실행파일을 읽어들이고, text/data/bss/stack을 만든다. 특히 커널은 아규먼트와 환경변수를 위한 페이지를 할당하고 필요한 정보를 스택에 푸쉬한다.
  3. 이제 _start가 실행된다. _start는 스택에서 커널이 집어넣은 정보를 얻고, __libc_start_main을 위한 아규먼트 스택을 만든 후 이 함수를 부른다. 
  4. __libc_start_main은 필요한 것들을 (특별히 malloc같은 C 라이브러리와 쓰레드 환경) 초기화하고, 우리가 만든 main을 부른다. 
  5. main(argc, argv)로 우리가 만든 main을 부른다. 실제로 흥미로운 점은 main의 함수형이다. __libc_start_main은 main의 함수형이 main(int, char **, char **)라고 생각한다. 의심스러우면 다음 프로그램을 실행해봐라.
    main(int argc, char** argv, char** env)
    {
    int i = 0;
    while(env[i] != 0)
    {
    printf("%s\n", env[i++]);
    }
    return(0);
    }

결론

리눅스에서 우리가 만든 C main() 함수는 GCC, libc, 리눅스 바이너리 로더의 협력으로 실행된다.

참고자료

objdump                         "man objdump" 

ELF header                     /usr/include/elf.h 

__libc_start_main          glibc 소스 
                                       ./sysdeps/generic/libc-start.c 

sys_execve                     리눅스 커널 소스코드 
                                       arch/i386/kernel/process.c 

do_execve                      리눅스 커널 소스코드 
                                       fs/exec.c 

struct linux_binfmt       리눅스 커널 소스코드 
                                       include/linux/binfmts.h 

load_elf_binary             리눅스 커널 소스코드
                                       fs/binfmt_elf.c 

create_elf_tables           리눅스 커널 소스코드 
                                       fs/binfmt_elf.c 

start_thread                   리눅스 커널 소스코드 
                                      include/asm/processor.h

'개발 개발 > Android' 카테고리의 다른 글

Android에서 4gb 이상 비디오 돌리기  (0) 2011.11.15
ICS (IceCream Sandwitch) 소스가 나왔다.  (2) 2011.11.15
objdump  (0) 2011.11.14
Kconfig, Makefile, defconfig  (0) 2011.11.14
안드로이드 [Resource]리소스 폴더구조  (0) 2011.09.23
Locale 변경하기  (0) 2011.02.21
출처 : http://blog.naver.com/areema/60135756070


Kconfig, Makefile, defconfig

 

얘네들이 리눅스 시스템 개발 처음 시작할 때 가장 헷갈리고 가장 영향을 많이 줬던 녀석들이었다.

지금 생각해 보면 정말 별거 아닌 것 들인데 -..- 책에는 뭔가 어렵게만 적혀 있었던게 기억난다.

 

간단히 집고 넘어가보자

 

Makefile

 

말 그대로 파일을 생성하는 스크립트다. 예제를 하나 보자면



obj-y                += gpio/
obj-$(CONFIG_GPIO)        += gpio/

obj-y 의 y는 yes 라는 말로 gpio 폴더 내의 .o 파일들을 오브젝트 파일로 만들겠다 그 소리다. 참고로 / 가 붙어있는건 폴더라는 뜻이고 파일 한개만 지정하고 싶을 땐 .o 를 붙여주면 되겠다.

obj-$(CONFIG_GPIO) 는 뭐냐면 $(CONFIG_GPIO) 가 일종의 define 인데 이 define 이 바로.config 에 명시되어 있다. 음 근데 갑자기 .config 는 또 뭘까

 

.config 는 최상위 디렉토리 안에 위치하고 소스 안에는 이런것들이 명시되어 있다.

#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.35.7
# Thu Jul 28 18:03:53 2011
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_HAVE_SCHED_CLOCK=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_TIME=y

맞다. 위에서 본거다. CONFIG_GPIO 도 여기 어딘가에 정의가 되어있다.

그럼 .config는 어떻게 만드는걸까-

 

자동으로 만들어진다..

 

대신 Kconfig 를 참고해서-

 

다시 말하면 각 모듈마다 있는 Kconfig 에 y로 해놓을지 n을 해놓을지 명시를 해 놓으면 컴파일 될 때 자동으로 취합해서 하나의 파일인 .config 에 써지게 되는 것이다. 이 .config 는 다시 autoconf.h 라는 파일로 최종적으로 만들어 지게 된다.

 

Kconfig 에 대한 자세한 설명이 있는 블로그 : http://blog.daum.net/chazzing/20

 

자 다시 정리하자면 .ko 파일을 만드려면 Makefile 에 명시를 해줘야 하는데 그냥 y로 되있지 않고 $(CONFIG_XXX)라고 되어있으면 Kconfig에 가서

config GPIO
bool
default y

 

이렇게 해줘야지 된다. (참고로 Kconfig 에 config GPIO 라고 해 놓으면 .config 만들어 질 때 CONFIG_ 가 앞에 자동으로 붙게 되어있다.)

 

근데 보통 개발할 때 보면 FEATURE 처리가 되어 있을 때가 많다. 아래 처럼

if MSM_DEVICES
  config GPIO
  bool
  default y
endif

if 문이 하나 붙은걸 볼 수 있다. if 문이니까 MSM_DEVICES 가 true 일 경우에 아래 문장이 실행 되겠지-

말하자면 먼저 한번 걸러 주는 것이다.

암튼 저런 것을 FEATURE (피처) 처리 해준다고 하는데 요놈들은 defconfig 라는 파일에 명시되어 있다. 보통 kernel/arch/arm/config 폴더에 위치한다.

defconfig 라고 다를건 없다. y 로 해주든지 n 로 해주든지 그건 개발자 맘이다.

 

 

암튼 저렇게 해서 obj 파일에 포함이 되면은 최종적으로 .ko 파일이 만들어지게 된다. 뭔가 많이 길어졌네

책에 보면 Makefile 의 문법같은게 자세하게 나와있는데 내 생각엔 이정도만 알아도 드라이버 올리는덴 문제가 없다.

 

[출처] Kconfig, Makefile, defconfig|작성자 영승

'개발 개발 > Android' 카테고리의 다른 글

Android에서 4gb 이상 비디오 돌리기  (0) 2011.11.15
ICS (IceCream Sandwitch) 소스가 나왔다.  (2) 2011.11.15
objdump  (0) 2011.11.14
Kconfig, Makefile, defconfig  (0) 2011.11.14
안드로이드 [Resource]리소스 폴더구조  (0) 2011.09.23
Locale 변경하기  (0) 2011.02.21
출처 : http://blog.naver.com/rockhammer/80124449718

Resource 접근 방법

@[package:]type/name


종류 : xml기반의 리소스, 미가공리소스(raw resource), 애셋(asset)

일반 리소스의 경우 AAPT(Android Asset Packaging Tool)로 바이너리로 컴파일 된 후에 최종 .apk파일에 포함된다.

크게 나누면 리소스는 최종 .apk파일이 만들어질때 바이너리 형태 여부를 가지고 나눌 수 있다.

바이너리 형태 / 일반 형태


만들어진 리소스는 Eclipse의 /gen/pacakge-name/R.java 파일에 상수로 정의되어진다.


리소스 폴더

/assets - 일반 파일들로 /assets를 제외한 상대 경로로 접근 가능하다.

/res 

    /anim - 컴파일된 애니메이션 파일

    /drawable - 비트맵

    /layout - UI/뷰 정의

    /values - 배열, 컬러, 치수, 문자열, 스타일

    /xml - 컴파일된 xml파일, R.xml.xx로 접근

    /raw - 컴파일 되지 않은 미가공 파일, R.raw.xx로 접근 가능


리소스가 추가 되면 R.java파일이 업데이트가 되므로 추가가 정상적으로 되었는지 여부는 R.java 파일을 확인하면 된다.

'개발 개발 > Android' 카테고리의 다른 글

Android에서 4gb 이상 비디오 돌리기  (0) 2011.11.15
ICS (IceCream Sandwitch) 소스가 나왔다.  (2) 2011.11.15
objdump  (0) 2011.11.14
Kconfig, Makefile, defconfig  (0) 2011.11.14
안드로이드 [Resource]리소스 폴더구조  (0) 2011.09.23
Locale 변경하기  (0) 2011.02.21
android/build/target/product/core.mk

PRODUCT_LOCALES := \
    ko_KR \
    en_US

'개발 개발 > Android' 카테고리의 다른 글

Android에서 4gb 이상 비디오 돌리기  (0) 2011.11.15
ICS (IceCream Sandwitch) 소스가 나왔다.  (2) 2011.11.15
objdump  (0) 2011.11.14
Kconfig, Makefile, defconfig  (0) 2011.11.14
안드로이드 [Resource]리소스 폴더구조  (0) 2011.09.23
Locale 변경하기  (0) 2011.02.21