접미사플래그의미
EQ Z 세트 같음
NE Z 지우기 같지 않음
CS or HS C 세트 높거나 같음 (부호 없는 >= )
CC or LO C 지우기 보다 낮음 (부호 없는 < )
MI N 세트 음수
PL N 지우기 양수 또는 0
VS V 세트 오버플로
VC V 지우기 오버플로 없음
HI C 설정 및 Z 지우기 보다 높음 (부호 없는 >)
LS C 지우기 또는 Z 설정 낮거나 같음 (부호 없는 <=)
GE N 및 V 같음 부호 있는 >=
LT N 및 V 다름 부호 있는 <
GT Z 지우기, N 및 V 같음 부호 있는 >
LE Z 설정, N 및 V 다름 부호 있는 <=
AL Any 항상. 이 접미사는 대개 생략됩니다.
Posted by blee
,
Posted by blee
,
링커 스크립터에 관한 문서 ( http://korea.gnu.org/manual/release/ld/ld-mahajjh/ld_3.html#SEC18 )
 

링커는 입력파일을 합쳐서 하나의 출력파일을 만든다. 링크 스크립터는 링킹 과정에서 링커의 동작을 제어 한다.

커널을 컴파일 하여  arch/arm/boot/compressed/vmlinux 이미지를 생성 할때, 다음과 같은 링킹 과정을 거친다.

/opt/codesourcery/bin/arm-linux-ld -EL --defsym zreladdr=0x40008000 \
  -p --no-undefined -X -T arch/arm/boot/compressed/vmlinux.lds \
  arch/arm/boot/compressed/head.o \
  arch/arm/boot/compressed/piggy.gzip.o \
  arch/arm/boot/compressed/misc.o \
  arch/arm/boot/compressed/decompress.o \
  arch/arm/boot/compressed/lib1funcs.o \
  -o arch/arm/boot/compressed/vmlinux


arm-linux-ld의 옵션 -T arch/arm/boot/compressed/vmlinux.lds 에 의해서 링커 스크립터를 지정 하였다.

-T FILE, --script FILE      Read linker script 


특별히 지정 하지 않았을 경우에는 default linker script를 사용하게 되는데, 이를 보는 옵션은 다음과 같다.
$ arm-linux-ld --verbose
GNU ld (Sourcery G++ Lite 2008q3-41) 2.18.50.20080215
  Supported emulations:
   armelf_linux_eabi
   armelfb_linux_eabi
using internal linker script:
==================================================
/* Script for -z combreloc: combine and sort reloc sections */
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
              "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
SECTIONS
{
  /* Read-only sections, merged into text segment: */
  PROVIDE (__executable_start = 0x00008000); . = 0x00008000 + SIZEOF_HEADERS;
  .interp         : { *(.interp) }
  .note.gnu.build-id : { *(.note.gnu.build-id) }
  .hash           : { *(.hash) }
  .gnu.hash       : { *(.gnu.hash) }
  .dynsym         : { *(.dynsym) }
  .dynstr         : { *(.dynstr) }
  .gnu.version    : { *(.gnu.version) }
  .gnu.version_d  : { *(.gnu.version_d) }
  .gnu.version_r  : { *(.gnu.version_r) }
  .rel.dyn        :
    {
      *(.rel.init)
      *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
      *(.rel.fini)
      *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
      *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
      *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
      *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
      *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
      *(.rel.ctors)
      *(.rel.dtors)
      *(.rel.got)
      *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
    }
  .rela.dyn       :
    {
      *(.rela.init)
      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
      *(.rela.fini)
      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
      *(.rela.ctors)
      *(.rela.dtors)
      *(.rela.got)
      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
    }
  .rel.plt        : { *(.rel.plt) }
  .rela.plt       : { *(.rela.plt) }
  .init           :
  {
    KEEP (*(.init))
  } =0
  .plt            : { *(.plt) }
  .text           :
  {
    *(.text .stub .text.* .gnu.linkonce.t.*)
    /* .gnu.warning sections are handled specially by elf32.em.  */
    *(.gnu.warning)
    *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)
  } =0
  .fini           :
  {
    KEEP (*(.fini))
  } =0
  PROVIDE (__etext = .);
  PROVIDE (_etext = .);
  PROVIDE (etext = .);
  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
  .rodata1        : { *(.rodata1) }
  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) }
   __exidx_start = .;
  .ARM.exidx   : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
   __exidx_end = .;
  .eh_frame_hdr : { *(.eh_frame_hdr) }
  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
  /* Adjust the address for the data segment.  We want to adjust up to
     the same address within the page on the next page up.  */
  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
  /* Exception handling  */
  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
  /* Thread Local Storage sections  */
  .tdata          : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
  .tbss           : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  }
  .init_array     :
  {
     PROVIDE_HIDDEN (__init_array_start = .);
     KEEP (*(SORT(.init_array.*)))
     KEEP (*(.init_array))
     PROVIDE_HIDDEN (__init_array_end = .);
  }
  .fini_array     :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(.fini_array))
    KEEP (*(SORT(.fini_array.*)))
    PROVIDE_HIDDEN (__fini_array_end = .);
  }
  .ctors          :
  {
    /* gcc uses crtbegin.o to find the start of
       the constructors, so we make sure it is
       first.  Because this is a wildcard, it
       doesn't matter if the user does not
       actually link against crtbegin.o; the
       linker won't look for a file to match a
       wildcard.  The wildcard also means that it
       doesn't matter which directory crtbegin.o
       is in.  */
    KEEP (*crtbegin.o(.ctors))
    KEEP (*crtbegin?.o(.ctors))
    /* We don't want to include the .ctor section from
       the crtend.o file until after the sorted ctors.
       The .ctor section from the crtend file contains the
       end of ctors marker and it must be last */
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
  }
  .dtors          :
  {
    KEEP (*crtbegin.o(.dtors))
    KEEP (*crtbegin?.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
  }
  .jcr            : { KEEP (*(.jcr)) }
  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
  .dynamic        : { *(.dynamic) }
  . = DATA_SEGMENT_RELRO_END (0, .);
  .got            : { *(.got.plt) *(.got) }
  .data           :
  {
    __data_start = . ;
    *(.data .data.* .gnu.linkonce.d.*)
    SORT(CONSTRUCTORS)
  }
  .data1          : { *(.data1) }
  _edata = .; PROVIDE (edata = .);
  __bss_start = .;
  __bss_start__ = .;
  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   /* Align here to ensure that the .bss section occupies space up to
      _end.  Align after .bss to ensure correct alignment even if the
      .bss section disappears because there are no input sections.
      FIXME: Why do we need it? When there is no .bss section, we don't
      pad the .data section.  */
   . = ALIGN(. != 0 ? 32 / 8 : 1);
  }
  _bss_end__ = . ; __bss_end__ = . ;
  . = ALIGN(32 / 8);
  . = ALIGN(32 / 8);
  __end__ = . ;
  _end = .; PROVIDE (end = .);
  . = DATA_SEGMENT_END (.);
  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }
  /* DWARF 3 */
  .debug_pubtypes 0 : { *(.debug_pubtypes) }
  .debug_ranges   0 : { *(.debug_ranges) }
  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
  .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) }
}


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


실제로 arch/arm/boot/compressed/vmlinux 이미지를 생성 할때 사용되는 링커 스크립터를 보자.
아래는 arch/arm/boot/compressed/vmlinux.lds 파일의 내용이다.
 

/*
 *  linux/arch/arm/boot/compressed/vmlinux.lds.in
 *
 *  Copyright (C) 2000 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
  /DISCARD/ : {
    *(.ARM.exidx*)
    *(.ARM.extab*)
    /*
     * Discard any r/w data - this produces a link error if we have any,
     * which is required for PIC decompression.  Local data generates
     * GOTOFF relocations, which prevents it being relocated independently
     * of the text/got segments.
     */
    *(.data)
  }

  . = 0; /* 주소를 0x0 으로 지정한다. */
  _text = .; /* 이 곳에 심볼 _text 를 정의한다. 코드 영역의 시작 지정 */

  .text : { /* 섹션이름 .text 영역 정의 */
    _start = .; /* 이 곳에 심볼 _start 를 정의한다. */
    *(.start) /* .start 섹션으로 정의된 코드 부터 차례로 배열 된다. */
    *(.text)
    *(.text.*)
    *(.fixup)
    *(.gnu.warning)
    *(.glue_7t)
    *(.glue_7)
  }
  .rodata : { /* 섹션이름 .rodata 영역 정의 */
    *(.rodata)
    *(.rodata.*)
  }
  .piggydata : { /* 섹션이름 .piggydata 영역 정의 */
    *(.piggydata)
  }

  . = ALIGN(4);
  _etext = .; /* 이 곳에 심볼 _etext 를 정의한다. 코드 영역의 끝 지정 */

  .got.plt : { *(.got.plt) }
  _got_start = .;
  .got : { *(.got) } /* got 영역 */
  _got_end = .;
  _edata = .;

  . = ALIGN(8);
  __bss_start = .;
  .bss : { *(.bss) } /* bss 영역 */
  _end = .;

  . = ALIGN(8); /* the stack must be 64-bit aligned */
  .stack : { *(.stack) }

  .stab 0 : { *(.stab) }
  .stabstr 0 : { *(.stabstr) }
  .stab.excl 0 : { *(.stab.excl) }
  .stab.exclstr 0 : { *(.stab.exclstr) }
  .stab.index 0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment 0 : { *(.comment) }

} 


스크립터에 사용 된 명령을 살펴 보자.
OUT_ARCH(arm) : 출력 아키텍쳐를 지정한다.
ENTRY(_start) : 프로그램에서 처음 실행되는 진입점이다. 심볼명을 지정한다.
SECTION  { } : 링커가 어떻게 입력 섹션을 출력 섹션으로 대응하고, 출력 섹션을 메모리에 배치하는지를 지정한다.

'/DISCARD/' : 특별한 출력 세션 이름으로 입력 섹션을 버리는 용도로 사용한다. 이 섹션으로 지정된 입력은 실제로 출력으로 배치되지 않는다.

objdump -h 명령으로 어떠한 섹션이 있는지 살펴 보자.

$ arm-linux-objdump -h arch/arm/boot/compressed/vmlinux

arch/arm/boot/compressed/vmlinux:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00003b50  00000000  00000000  00008000  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rodata       00000c94  00003b50  00003b50  0000bb50  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .piggydata    0012bf8c  000047e4  000047e4  0000c7e4  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .got.plt      0000000c  00130770  00130770  00138770  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  4 .got          0000002c  0013077c  0013077c  0013877c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  5 .bss          00000020  001307a8  001307a8  001387a8  2**2
                  ALLOC
  6 .stack        00001000  001307c8  001307c8  001387a8  2**0
                  ALLOC
  7 .comment      00000054  00000000  00000000  001387a8  2**0
                  CONTENTS, READONLY
  8 .ARM.attributes 00000029  00000000  00000000  001387fc  2**0
                  CONTENTS, READONLY
  9 .debug_line   0000107d  00000000  00000000  00138825  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_info   000018bc  00000000  00000000  001398a2  2**0
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_abbrev 00000633  00000000  00000000  0013b15e  2**0
                  CONTENTS, READONLY, DEBUGGING
 12 .debug_aranges 00000088  00000000  00000000  0013b798  2**3
                  CONTENTS, READONLY, DEBUGGING
 13 .debug_ranges 00000548  00000000  00000000  0013b820  2**3
                  CONTENTS, READONLY, DEBUGGING
 14 .debug_frame  000001f8  00000000  00000000  0013bd68  2**2
                  CONTENTS, READONLY, DEBUGGING
 15 .debug_loc    00002791  00000000  00000000  0013bf60  2**0
                  CONTENTS, READONLY, DEBUGGING
 16 .debug_pubnames 000001a4  00000000  00000000  0013e6f1  2**0
                  CONTENTS, READONLY, DEBUGGING
 17 .debug_str    00000688  00000000  00000000  0013e895  2**0
                  CONTENTS, READONLY, DEBUGGING


출력되는 섹션의 배치를 간략하게 그림으로 표현했다.



코드상에서 정의된 심볼의 값

        .word   0x016f2818                                 |      24:   016f2818    .word   0x016f2818
        .word   start                                         |      28:   00000000    .word   0x00000000
        .word   _edata                                      |      2c:   001307a8    .word   0x001307a8


        .type   LC0, #object                               |0000017c <LC0>:
LC0:        .word   LC0                                    |     17c:   0000017c    .word   0x0000017c
        .word   __bss_start                                |     180:   001307a8    .word   0x001307a8
        .word   _end                                         |     184:   001307c8    .word   0x001307c8
        .word   _edata                                      |     188:   001307a8    .word   0x001307a8
        .word   input_data_end - 4                     |     18c:   0013076c    .word   0x0013076c
        .word   _got_start                                  |     190:   0013077c    .word   0x0013077c
        .word   _got_end                                   |     194:   001307a8    .word   0x001307a8
        .word   .L_user_stack_end                     |     198:   001317c8    .word   0x001317c8
        .size   LC0, . - LC0                               |     19c:   e1a00000    .word   0xe1a00000


Posted by blee
,
커널 분석의 시작 점은 크게 두가지 차이가 있다.
1. 커널를 압축해제 하는 부분
2. 순수 커널의 시작 부분 

또한 임베디드 시스템을 구성 할 경우 시스템의 저장 공간(일반적으로 ROM)에  퓨징 하는 커널도 두 가지로 구분 할 수 있다.
1. 압축된 커널을 퓨징해서 사용하는 경우
2. 압축되지 않은 커널을 퓨징해서 사용하는 경우

부트로더 입장에서는 압축 해제는 커널에서 하기 때문에 두가지의 차이가 없다.
저장 공간의 용량이 변수가 된다면, 1번 항을 선택 할 것이며, 좀 더 빠른 부팅을 원한다면, 2번 항을 선택하게 된다.

커널 분석을 시작하는 지점이 꼭 정해져 있는 것은 아니라고 본다. 
시간을 단축하고자 할때는 압축 해제 코드는 그냥 무시 해도 된다는 것이다.
스터디를 시작하는 단계에서 이러한 부분이 가끔 논쟁이 되기도 한다. 

이전 글의 make 로그 과정에서 이미지 생성 과정을 다시 살펴보면, 아래의 그림과 같이 요약 할 수 있다.



순수 커널 부분이 1) vmlinux 이며, 압축 해제 코드와 압축된 커널은 2) vmlinux 가 된다.

그럼 각각 시작 부분을 살펴 보자. 두번째 2) vmlinux 의 시작 부분을 링커스크립터를 통해서 살펴 보자.
이때 빌드 시 사용하는  링커스크립터는 arch/arm/boot/compressed/vmlinux.lds 이다.

$ head -n 20 arch/arm/boot/compressed/vmlinux.lds
/*
 *  linux/arch/arm/boot/compressed/vmlinux.lds.in
 *
 *  Copyright (C) 2000 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
OUTPUT_ARCH(arm)
ENTRY(_start) /* 시작 심볼 지정 */
SECTIONS
{
  /DISCARD/ : {
    *(.ARM.exidx*)
    *(.ARM.extab*)
    /*
     * Discard any r/w data - this produces a link error if we have any,
     * which is required for PIC decompression.  Local data generates
     * GOTOFF relocations, which prevents it being relocated independently
     * of the text/got segments.
     */
    *(.data)
  }

  . = 0;
  _text = .;

  .text : {
    _start = .;        /* [BLEE] _start 심볼을 정의함 , ENTRY(_start) 지정이 이곳이라고 본다. */
    *(.start)
    *(.text)
:


ENTRY 가 _start 로 지정되어 있다. 
다음으로 objdump 한 어셈블리 코드를 살펴 보자.
 

$ head -n 20 arch/arm/boot/compressed/vmlinux.objdump

vmlinux:     file format elf32-littlearm

Disassembly of section .text:

00000000 <start>:
       0:       e1a00000        nop                     (mov r0,r0)
       4:       e1a00000        nop                     (mov r0,r0)
       8:       e1a00000        nop                     (mov r0,r0)
       c:       e1a00000        nop                     (mov r0,r0)
      10:       e1a00000        nop                     (mov r0,r0)
      14:       e1a00000        nop                     (mov r0,r0)
      18:       e1a00000        nop                     (mov r0,r0)
      1c:       e1a00000        nop                     (mov r0,r0)
      20:       ea000002        b       30 <_text+0x30>
      24:       016f2818        .word   0x016f2818
      28:       00000000        .word   0x00000000
      2c:       001307a8        .word   0x001307a8
      30:       e1a07001        mov     r7, r1
      34:       e1a08002        mov     r8, r2

 
0 번지가 start 로 지정되어 있다. 여기서 한 가지 의문이 드는데, 링커스크립터에서는 _start 라고 되어 있는데, 실제로 objdump 한 파일에서는 start 라고 되어 있다. 링커스크리터에서 ENTRY()는 심볼를 지정하게 되었는데, 링커스크립터 내에서 _start 심볼을 .start 섹션의 처음 부분으로 지정하고 있다. 

이 부분의 시작 코드는 arch/arm/boot/compressed/head.S 의 start 심볼이다.

첫번째 1) vmlinux의 시작 부분을 링커스크립터를 통해서 살펴 보자.

$ vi arch/arm/kernel/vmlinux.lds

OUTPUT_ARCH(arm)
ENTRY(stext)
jiffies = jiffies_64;
SECTIONS
{


 ENTRY 가 stext 로 지정되어 있다. 
 다음으로 objdump 한 파일로 첫 시작 부분을 살펴 보자.
 

$ head -n 20 vmlinux.objdump

vmlinux:     file format elf32-littlearm

Disassembly of section .head.text:

c0008000 <stext>:
c0008000:       e321f0d3        msr     CPSR_c, #211    ; 0xd3
c0008004:       ee109f10        mrc     15, 0, r9, cr0, cr0, {0}
c0008008:       eb061b5a        bl      c018ed78 <__lookup_processor_type>
c000800c:       e1b0a005        movs    sl, r5
c0008010:       0a061b69        beq     c018edbc <__error_p>
c0008014:       e28f302c        add     r3, pc, #44     ; 0x2c
c0008018:       e8930110        ldm     r3, {r4, r8}
c000801c:       e0434004        sub     r4, r3, r4
c0008020:       e0888004        add     r8, r8, r4
c0008024:       eb00004b        bl      c0008158 <__vet_atags>
c0008028:       eb0873f4        bl      c0225000 <__init_begin>
c000802c:       eb000007        bl      c0008050 <__create_page_tables>
c0008030:       e59fd00c        ldr     sp, [pc, #12]   ; c0008044 <stext+0x44>
c0008034:       e28fe004        add     lr, pc, #4      ; 0x4

 

이 부분의 시작 코드는 arch/arm/kernel/head.S 의 stext 심볼이다.
Posted by blee
,
커널 버젼은 3.x , CPU는 ARM 멀티코어인 exynos4를 선택한다.

1. 커널 소스 받기
 
2. 툴체인 설치하기
  1) codesourcery 에서 다운로드 ( http://www.codesourcery.com/sgpp/lite/arm )
  2) root 권한으로 설치

$ cd /
$ tar zxvf /다운로드경로/codesourcery.tar.gz
$
  3) 툴체인은 codesourcery 것을 사용한다.
     일전에 3개의 툴체인을 동일한 환경에서 벤치마크를 한 적이 있다.
     예상대로 
codesourcery가 가장 빠른 성능을 보였다. 

  4) 예전에 받은 것을 그대로 사용한다. 만약 최근에 릴리즈 된 툴체인을 사용하려 한다면, 다운로드 URL과
      설치 경로가 지금 기록과 다를 수 있다.
 
3. 환경변수 설정 및 컴파일 테스트
  1) 툴체인의 설치 경로는 /opt/codesourcery/ 밑으로 된다.
  2) 환경변수 PATH에 컴파일러 및 실행 가능한 파일의 경로 /opt/codesourcery/bin 를 추가한다.
  3) 툴체인을 검증하기 위해서 테스트로 컴파일 해 본다.

$ export PATH=$PATH:/opt/codesourcery/bin
$ arm-none-linux-gnueabi-gcc -o test test.c
$

  4) 로그인시 자동 설정되도록 ~/.bash_profile 수정

$ vi ~/.bash_profile
PATH=$PATH:$HOME/bin:/sbin:/opt/codesourcery/bin
export PATH


4. 커널 컴파일

$ cd /KERNEL_ROOT/
$ export ARCH=arm
$ export CROSS_COMPILE=/opt/codesourcery/bin/arm-linux-
$ make distclean
$ make exynos4_defconfig
$ make V=1 > make.out 2>&1
$
  1) 환경변수 ARCH, CROSS_COMPILE를 설정 하는 이유는 별도의 Makefile 수정 없이
      해당 ARCH와 툴체인으로 컴파일 하기 위해서다. 
  2) 커널 설정은 exynos4_defconfig ( arch/arm/configs/exynos4_defconfig ) 를 기본으로
      특별한 변경없이 사용한다.
  3) make 의 V=1 옵션은 컴파일 내용을 자세히 출력하고, make.out 으로 리다이렉션 하는 것은
     혹, 나중에 컴파일 과정이 궁금해 질 수 있기 때문이다.
 
5. ctags, cscope 생성

$ export ARCH=arm
$ export CROSS_COMPILE=/opt/codesourcery/bin/arm-linux-
$ rm -f tags cscope.*
$ make tags
$ make cscope

  1) make 에 의한 ctags, cscope의 생성은 검색 되는 코드의 ARCH 가 arm에 존속되도록 한다.
 
6. 어셈블리 코드 생성
  1) 커널의 어셈블리 코드 생성

$ arm-linux-objdump -d vmlinux > vmlinux.objdump


  2) 압축된 커널의 어셈블리 코드 생성

$ cd arch/arm/boot/compressed/
$ arm-linux-objdump -d vmlinux > vmlinux.objdump
  3) 어셈블리 코드를 생성 해 두는 이유는 소스 분석 중에 복잡한 전처리 과정,
      코드의 살리고, 버리는 부분이 모호 할때, 상수 값이 모호 할때 참조 하면 유용하다.
 
Posted by blee
,