프로그래머가 코딩을 처음 배울 때, 아주아주 처음 배우면 먼저 해보는 Helloworld!.


#include<stdio.h>


int main(int argc, char **argv)

{

    printf("Hello World\n");

    return 0;


이 코드를 작성해서 터미널에 

gcc helloworld.c -o helloworld 라고 명령어를 치거나, Visual-Studio를 통해서 Run 버튼을 누르면, 결과창에 나타나는 것은 Hello World라는 한 줄이다.


왜 인지는 모르지만, main 이라는 함수를 실행하는거 보니, 이 프로그램은 main 이라는 함수가 시작지점 즉, Entry-point 인가 보다 하면서 공부를 시작했던게 기억난다. 시간이 지나고 보니 내가 했던 생각은 맞기도, 틀리기도 한 내용이다. 엄밀히 말하면 틀리기 보다는 똑똑한 운영체제가 나 대신에 Entry-point를 main함수로 지정해 준 것이라는걸(운영체제가 main함수를 엔트리 포인트로 하고 있는, 디폴트 링커스크립트를 제공해준다는 걸) 나중에 머리가 조금 크고 나니 알게 되었다.


프로그램을 작성하려면 내 코드를 기계어로 바꿔주는 컴파일러에게 "내가 만든 이 코드들을 여기부터 시작해야되!" 라는 힌트를 제공해주어야 한다. 사실, Entry-point 말고도 여러가지 힌트들을 제공해주어야 하는데 링커스크립트를 통해서 제공해준다.


바로 위 문장을 보고나면 아래와 같은 질문들이 생긴다.

  • 링커스크립트(Linker-Script)가 뭔대?!
  • 어떠한 힌트들을 제공해 주는데?
  • Entry-point에 대한 힌트는 어떻게 제공하는데?
모든 질문에 대한 답은 나중에 다른 글을 통해서 알게되겠지만, 이 글에서는 마지막 질문에 대해서만 대답해보려 한다.
링크를 눌러 한 번 살펴보면, ENTRY라는 명령어 또는 지시어 라고 불리는 함수 같이 생긴 놈을 호출하는 형식으로 내 프로그램이 처음으로 시작되는 지점을 컴파일러에게 힌트로 제공하는 셈이다. 컴파일러는 내가 만든 코드들을 기계어로 바꿔주는 역할을 하고, 이러한 컴파일러에게 
"너가 만든 기계어 중에서 제일 먼저 시작되어야 할 기계어는 이거야" 라고 말을 해주어야 하는 셈이다.

리눅스 커널의 링커스크립트를 살펴보면,

<linux/arch/arm64/kernel/vmlinux.lds.S>


이렇게 _text라는 심볼을 리눅스의 처음 시작 지점으로 할게! 라고 컴파일러에게 정보를 제공해주고 있다.


이처럼 링커스크립트에서 ENTRY라는 지시어는 프로그램의 시작지점 즉 엔트리 포인트를 지정해주는 지시어! 이다.




 










'전공공부 > ARM' 카테고리의 다른 글

ARM Relocations (adrp)  (0) 2020.10.18
[ARM] Alignment가 무엇인가?!  (0) 2019.02.17
GICv3 LPI, ITS  (0) 2018.07.18
interrupt status - level sensitive  (0) 2018.07.17
ARMv8 HPPIR/IAR, AHPPIR/AIAR  (0) 2018.03.27

리눅스 커널을 Line-by-line으로 분석하려면, 특히 리눅스 커널 이미지가 처음부터 실행되는 모습을 보고자 한다면!

몇 가지 배경 지식을 알고 있어야 한다.


이 간단한 배경 지식들을 알게 되었거나 링크를 눌러보면서 읽고 알게 되었다면 이제부터!

Linux를 Line-by-line으로 보기 위해서 리눅스의(ARM architecture의 arm64) 처음 시작점부터 알아보려고한다. 



1

2

3

4

5

6

7

8

 ENTRY(_text)


    ...

. = KIMAGE_VADDR + TEXT_OFFSET;

.head.text : {
    _text = .;
    HEAD_TEXT
}


첫 번째 줄이 바로 위에 설명한 ENTRY 지시어이다. 이는 "지금 컴파일의 결과물로 나오는 프로그램 이미지의 시작은 _text 라는 symbol이다." 라는 뜻이며 이러한 정보를 컴파일러에게 힌트로 제공해주는 것이다.

다섯 번 째 줄은 컴파일의 결과물 즉, 이 프로그램 이미지는 ".head.text" 라는 섹션을 포함하는데 이 섹션에는 이러한 내용들이 들어가 있다.
이 section에서 _text 심볼의 값을 assign해주고 있는데 그 값은 "." 즉, 위에 KIMAGE_VADDR + TEXT_OFFSET에 해당하는 값이다.
그리고 7 번째 줄에 있는 HEAD_TEXT라는 매크로 살펴보면

#define HEAD_TEXT  KEEP(*(.head.text)) 


이와 같이 정의되어있다. Linking 할 모든 Object 파일들의 "head.text" section을 모아 여기에 링킹 하겠다 하는 의미이다.

밑에서 head.S 내용에서 보겠지만 head.S의 일부 코드도 이 section에 포함되어있는 코드들이다.


그럼 이제 이러한 배경 지식을 갖고 리눅스의 처음(head.S) 으로 가보겠다.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32

     __HEAD
_head:
    /*
     * DO NOT MODIFY. Image header expected by Linux boot-loaders.
     */
#ifdef CONFIG_EFI
    /*
     * This add instruction has no meaningful effect except that
     * its opcode forms the magic "MZ" signature required by UEFI.
     */
    add    x13, x18, #0x16
    b    stext
#else
    b    stext                // branch to kernel start, magic
    .long    0                // reserved
#endif
    le64sym    _kernel_offset_le        // Image load offset from start of RAM, little-endian
    le64sym    _kernel_size_le            // Effective size of kernel image, little-endian
    le64sym    _kernel_flags_le        // Informative flags, little-endian
    .quad    0                // reserved
    .quad    0                // reserved
    .quad    0                // reserved
    .ascii    ARM64_IMAGE_MAGIC        // Magic number
#ifdef CONFIG_EFI
    .long    pe_header - _head        // Offset to the PE header.

pe_header:
    __EFI_PE_HEADER
#else
    .long    0                // reserved
#endif



첫 번째 줄에 _HEAD라는 매크로는 아래와 같이 정의되어있고, 위에서 설명한 것 처럼 _text 실볼에 해당하는 section이다.

#define __HEAD        .section    ".head.text","ax" 


EFI를 사용하지 않고 있다고 가정하고있으므로, Image의 첫번째 명령어는 14번째 줄이 될 것이다.

부트로더가 리눅스를 실행시키면 14번 째 줄 명령어를 처음으로 실행하게 되고, 즉 stext 함수를 실행하게 된다.


다음부터는 stext 함수에 대해서 보겠다.







따로 만들어야 하는 문서: 링커스크립트, ELF, 섹션

LPI: Locality-specific Peripheral Interrupt

ITS: Interrupt Translation Service


GICv3에는 기존 GICv2와는 다르게 위 내용들이 추가되었다.




출처: http://infocenter.arm.com/help/topic/com.arm.doc.dai0492b/GICv3_Software_Overview_Official_Release_B.pdf

'전공공부 > ARM' 카테고리의 다른 글

ARM Relocations (adrp)  (0) 2020.10.18
[ARM] Alignment가 무엇인가?!  (0) 2019.02.17
[링커스크립트] 지시어 ENTRY  (0) 2019.02.12
interrupt status - level sensitive  (0) 2018.07.17
ARMv8 HPPIR/IAR, AHPPIR/AIAR  (0) 2018.03.27


level sensitive only


  • Signaling from device to GIC: interrupt state: Pending
  • Sending the signal from GIC to CPU: Pending
  • Acknowledge (ACK) the interrupt through CPU interface: Active & Pending
  • Operating System reprogram the device and device switch from high to low: Active
  • CPU deactivate(write corresponding interrupt to EOI) the interrupt: Active to Inactive


'전공공부 > ARM' 카테고리의 다른 글

ARM Relocations (adrp)  (0) 2020.10.18
[ARM] Alignment가 무엇인가?!  (0) 2019.02.17
[링커스크립트] 지시어 ENTRY  (0) 2019.02.12
GICv3 LPI, ITS  (0) 2018.07.18
ARMv8 HPPIR/IAR, AHPPIR/AIAR  (0) 2018.03.27

 

 Non-secure

Secure 

 HPPIR/IAR

Grp1 ID / 1023 

Grp0 ID 

Grp1 pending: 1022,

No pending; 1023 

 AHPPIR/AIAR

 -

Grp1 ID 

No Pending: 1023 


'전공공부 > ARM' 카테고리의 다른 글

ARM Relocations (adrp)  (0) 2020.10.18
[ARM] Alignment가 무엇인가?!  (0) 2019.02.17
[링커스크립트] 지시어 ENTRY  (0) 2019.02.12
GICv3 LPI, ITS  (0) 2018.07.18
interrupt status - level sensitive  (0) 2018.07.17

개인적으로 공부하고 싶은 내용들에 대해서 List화 하고, 정리해 나갈 예정

[ x ]  : 시작 안함

[ - ]  : 진행 중

[ O ] : 완료



리눅스

    • [ - ] Linux Code Review line by line
    • [ x ] XEN on ARM Code Review line by line
    • [ x ] cgroup
    • [ x ] subsys


ARM

    • [ x ] ARMv8
    • [ x ] GICv3 & 4
    • [ x ] PMIC
    • [ x ] PSCI
    • [ x ] SMCCC
    • [ x ] ARM-EABI (Embedded Application Binary Interface)

Hardware

    • [ x ] 전기는 왜 흐르나
    • [ x ] flash memory
    • [ x ] EERPROM
    • [ x ] MMC
    • [ x ] eMMC
    • [ x ] UART (pl001x)


ETC

  • [ x ] ARM assembly .macro vs FUNC

  • [ x ] UEFI 사용해보기


git 계정 casionwoo@github.com 에서 casionwoo@gmail.com으로 바꾸기


git filter-branch --env-filter '

OLD_EMAIL="casionwoo@github.com"

CORRECT_NAME="casionwoo"

CORRECT_EMAIL="casionwoo@gmail.com"

if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]

then

    export GIT_COMMITTER_NAME="$CORRECT_NAME"

    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"

fi

if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]

then

    export GIT_AUTHOR_NAME="$CORRECT_NAME"

    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"

fi

' --tag-name-filter cat -- --branches --tags


git log -p -2

git push origin :(name of branch)

git pull --rebase (name of remote) (name of branch)

'전공공부 > Git' 카테고리의 다른 글

git 계정 바꾸기  (0) 2017.06.29
commit log 갯수 조절하기  (0) 2017.06.29
remote에 있는 branch 삭제하게  (0) 2017.06.29
내가 원하는 commit 시점으로 되돌아 가기  (0) 2017.06.29

+ Recent posts