Linker Script or Linker Command 라고 불리우며, Compiler에 따라 이 이름은 달라질 수 있다.
기능은 Linker에게 Command/Script로 명령을 주어 관련 Program을 환경설정을 변경하는 것이 주목적이다
일반 애플리케이션 사용자는 사용할 일은 거의 없을 것이라고 생각되며, Kernel / Uboot 같은 소스를 수정하는 사람들이 주로 사용하지만
요즘은 거의 사용할 일은 없다.
예를 들면, 주로 수정하여 고친다면, Interrupt Service Routine 을 새로 만들어서 SRAM에 올리거나,
예를 들면, 주로 수정하여 고친다면, Interrupt Service Routine 을 새로 만들어서 SRAM에 올리거나,
특정 Program 안에, 특정 Address 에 특정 Section을 만들어 할당하거나,
나만의 Section을 만들어 특정 Address 할당 하는데 주로 사용한다. (ROM/RAM/SRAM)
1.1. Linker Script 기본 Manual
일반적으로 컴파일러는 자동으로 Linker Script를 생성해서 만들어주므로, 크게 신경을 쓰지 않아도 된다.
http://korea.gnu.org/manual/release/ld/ld-sjp/ld-ko_3.html
http://www.scoberlin.de/content/media/http/informatik/gcc_docs/ld_3.html
http://www.math.utah.edu/docs/info/ld_3.html
1.2 GCC의 MACRO attribute
GCC Compiler의 MACRO인 attribute 설정과 Linker Script 밀접한 관계에 있으며, 이는 곳 특정영역에 넣는 것이 가능하다.
1.1. Linker Script 기본 Manual
일반적으로 컴파일러는 자동으로 Linker Script를 생성해서 만들어주므로, 크게 신경을 쓰지 않아도 된다.
하지만, 일반적으로 OS / Boot Loader 및 MCU 기반의 Compiler들은 ELF format을 직접이용하기보다는 특정영역에 확보하고 사용해야하는 프로그램은
관련 세부설정 부분들을 직접정의하고 각 소스에 이를 설정하여 연결한다.
주로확장자는 .ld or lds로 되어있지만, 컴파일러마다 조금씩 다를수 있으며, 이 파일들을 찾아 아래 메뉴얼들과 같이 보며
기본동작 방식을 이해하면 될 것 같다.
항상 세부적인것은 현재 사용중인 컴파일러 메뉴얼기반으로 봐야함
- GCC LD의 Linker Script 한글설명
반드시 참조하여 읽고 관련내용을 숙지
http://korea.gnu.org/manual/release/ld/ld-mahajjh/ld_3.htmlhttp://korea.gnu.org/manual/release/ld/ld-sjp/ld-ko_3.html
- 기타 Linker Script 영문설명
http://www.scoberlin.de/content/media/http/informatik/gcc_docs/ld_3.html
http://www.math.utah.edu/docs/info/ld_3.html
SECTIONS { . = 0x10000; .text : { *(.text) } . = 0x8000000; .data : { *(.data) } .bss : { *(.bss) } }
- 상위 SECTIONS 구성
- .text: code의 영역
- .data: 초기화된 전역변수 or static 변수
- .bss : 비초기화된 전역변수 or static 변수
- heap: bss 다음으로 연결되어지며, malloc/calloc과 연결
- .noinit: init를 하지 않는 전역변수
heap은 동적 Memory 저장하며, 일반적으로 stack은 함수호출 및 일반변수의 저장을 담당하며, heap기반으로 구성
https://en.wikipedia.org/wiki/Data_segment1.2 GCC의 MACRO attribute
GCC Compiler의 MACRO인 attribute 설정과 Linker Script 밀접한 관계에 있으며, 이는 곳 특정영역에 넣는 것이 가능하다.
예를드면, C/C++ Code에 MACRO인 attribute를 설정하여 Linker script와 연결하여 동작가능하다.
이는 GCC 뿐만 아니라 다른 Compiler라도 사용방법은 얼추 비슷하며, Linker Script의 이름은 변경될 수가 있다. (TI Compiler는 Linker Command)
이는 GCC 뿐만 아니라 다른 Compiler라도 사용방법은 얼추 비슷하며, Linker Script의 이름은 변경될 수가 있다. (TI Compiler는 Linker Command)
이외 Compiler 전용 MACRO가 있으므로, 그 부분은 각 Complier Manual 참조
Attribute는 Function 과 Variable 에 사용될 수 있으며, 각각 설정방법은 Manual을 보자.
https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Variable-Attributes.html#Variable-Attributes
https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/ARM-Pragmas.html#ARM-Pragmas
1.3 Kernel Linker Script 분석예제
Uboot/Kernel의 Linker Script를 분석들을 기본적으로 보고 이해를 하면될 것이고 더나아가 ISR 수정하거나, 변경한다면, 관련부분 전용 Linker Script 수정하면 될거 같다.
Linker Script 및 Kernel에 자료는 인터넷에 풍부하므로, 정리하지 않고, Link만 연결
- GCC Manual Index
GCC 전체 Manual 에 Index 기능으로 쉽게 보고자하는 파트를 찾을수 있다.
https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/- MACRO __attribute__
Function에 속성을 설정하여 Linker Script와 같이 연동하여 특정영역에 놓을 수도 있으며, 할당크기 및 다양한 설정이 가능하다
Variable , 즉 변수도 Linker Script와 같이 연동하여 특정영역뿐만 아니라 다양한 속성설정이 가능하다.
e.g. __atrribute__(section)
https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Function-Attributes.html#Function-Attributeshttps://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Variable-Attributes.html#Variable-Attributes
- MACRO #pragmas
https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/ARM-Pragmas.html#ARM-Pragmas
1.3 Kernel Linker Script 분석예제
Uboot/Kernel의 Linker Script를 분석들을 기본적으로 보고 이해를 하면될 것이고 더나아가 ISR 수정하거나, 변경한다면, 관련부분 전용 Linker Script 수정하면 될거 같다.
$ find . -name *.lds $ vi kernel/arch/arm/boot/compressed/vmlinux.lds $ vi kernel/arch/arm/kernel/vmlinux.lds
Linker Script 및 Kernel에 자료는 인터넷에 풍부하므로, 정리하지 않고, Link만 연결
- Makefile 과 Kernel Linker Script 분석
Makefile 과 Linker Script는 밀접하게 연관되어 있으며, 우선적으로 Makefile부터 분석해야, 현재 사용중인 Linker Script도 확인가능
https://wiki.kldp.org/KoreanDoc/html/EmbeddedKernel-KLDP/arm.makefile.html
https://wiki.kldp.org/KoreanDoc/html/EmbeddedKernel-KLDP/arm.makefile.html
- Kernel Linker Script 분석한 Blog들
Kernel Linker Script를 보면, 다양한 Section들이 나오며, 각 Section 의미를 알아보고 분석하자.
본인이 원하는 새로운 Section에 새로운 이름으로 만들어 추가도 가능하다.
아래보기전에, Linker Script Manual부터 확인
http://blee74.tistory.com/entry/Linker-script?category=249807
http://blee74.tistory.com/entry/%EB%8B%A4%EC%8B%9C-%EB%B3%B4%EB%8A%94-ARM-3x-%EC%BB%A4%EB%84%90-%EC%BB%A4%EB%84%90-%EB%B6%84%EC%84%9D-%EC%96%B4%EB%94%94%EC%84%9C-%EB%B6%80%ED%84%B0-%EC%8B%9C%EC%9E%91-%ED%95%98%EB%8A%94%EA%B0%80?category=249807
http://www.zdnet.co.kr/news/news_view.asp?artice_id=00000039134536
1.4 ARM Kernel 실제예제
ARM Makefile
http://blee74.tistory.com/entry/%EB%8B%A4%EC%8B%9C-%EB%B3%B4%EB%8A%94-ARM-3x-%EC%BB%A4%EB%84%90-%EC%BB%A4%EB%84%90-%EB%B6%84%EC%84%9D-%EC%96%B4%EB%94%94%EC%84%9C-%EB%B6%80%ED%84%B0-%EC%8B%9C%EC%9E%91-%ED%95%98%EB%8A%94%EA%B0%80?category=249807
http://www.zdnet.co.kr/news/news_view.asp?artice_id=00000039134536
1.4 ARM Kernel 실제예제
ARM Makefile
LDFLAGS 와 각 CONFIG기반의 Address 와 소스확인
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/Makefile
ARM Kernel Image
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/Makefile
ARM Kernel Image
build 후에는 System.map기반으로 확인하고, boot 관련부분을 확인
반드시 Kernel CONFIG와 같이 확인
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/boot
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/boot/compressed/Makefile
MMU/SMP/XIP/TCM 등 각 설정기반의 설정확인
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/boot
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/boot/compressed/Makefile
MMU/SMP/XIP/TCM 등 각 설정기반의 설정확인
http://elixir.free-electrons.com/linux/v3.19.7/source/arch/arm/boot/compressed/vmlinux.lds.S
ARM Kernel Vmlinux
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/kernel
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/kernel/Makefile
http://elixir.free-electrons.com/linux/v3.19.7/source/arch/arm/kernel/vmlinux.lds.S
빌드후, 아래와 같이 arch/arm/kernel/vmlinux.lds 생성
ARM IRQ 관련 부분
http://elixir.free-electrons.com/linux/v3.19.7/source/arch/arm/kernel/irq.c
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/include/asm/exception.h#L14
http://elixir.free-electrons.com/linux/v3.19.7/source/arch/arm/kernel/fiq.c
IRQENTRY_TEST
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/kernel/vmlinux.lds.S
https://elixir.bootlin.com/linux/v3.19.7/source/include/asm-generic/vmlinux.lds.h#L440
asmlikage 의 의미
http://egloos.zum.com/studyfoss/v/4951809
ARM Kernel Vmlinux
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/kernel
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/kernel/Makefile
http://elixir.free-electrons.com/linux/v3.19.7/source/arch/arm/kernel/vmlinux.lds.S
빌드후, 아래와 같이 arch/arm/kernel/vmlinux.lds 생성
ARM IRQ 관련 부분
http://elixir.free-electrons.com/linux/v3.19.7/source/arch/arm/kernel/irq.c
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/include/asm/exception.h#L14
http://elixir.free-electrons.com/linux/v3.19.7/source/arch/arm/kernel/fiq.c
IRQENTRY_TEST
https://elixir.bootlin.com/linux/v3.19.7/source/arch/arm/kernel/vmlinux.lds.S
https://elixir.bootlin.com/linux/v3.19.7/source/include/asm-generic/vmlinux.lds.h#L440
- ARM의 IRQ 부분
---------------------------arch/arm/kernel/irq.c asmlinkage void __exception_irq_entry // Exception 영역으로 asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { handle_IRQ(irq, regs); } ---------------------------arch/arm/include/asm/exception.h #define __exception __attribute__((section(".exception.text"))) // GCC attribute 관련부분 참조 #ifdef CONFIG_FUNCTION_GRAPH_TRACER #define __exception_irq_entry __irq_entry #else #define __exception_irq_entry __exception #endif ---------------------------include/asm-generic/vmlinux.lds.h #ifdef CONFIG_FUNCTION_GRAPH_TRACER // CONFIG가 존재하면 사용함 #define IRQENTRY_TEXT \ ALIGN_FUNCTION(); \ VMLINUX_SYMBOL(__irqentry_text_start) = .; \ *(.irqentry.text) \ VMLINUX_SYMBOL(__irqentry_text_end) = .; #else #define IRQENTRY_TEXT #endif ---------------------------arch/arm/kernel/vmlinux.lds.S .text : { /* Real text segment */ _stext = .; /* Text and read-only data */ __exception_text_start = .; *(.exception.text) // 상위 exception 영역 __exception_text_end = .; IRQENTRY_TEXT // header file define 되어있음 TEXT_TEXT SCHED_TEXT LOCK_TEXT KPROBES_TEXT IDMAP_TEXT #ifdef CONFIG_MMU *(.fixup) #endif *(.gnu.warning) *(.glue_7) *(.glue_7t) . = ALIGN(4); *(.got) /* Global offset table */ ARM_CPU_KEEP(PROC_INFO) }
asmlikage 의 의미
http://egloos.zum.com/studyfoss/v/4951809
- ARM9에서 많이 사용했던 TCM 관련부분
ARM9뿐만아니라, Cortex에서도 사용되며, 예를 들면, Deep Sleep용 ISR 기능 뿐만아니라, 다양한 빠른 Latency 목적으로 사용가능하다고 한다.
#ifdef CONFIG_HAVE_TCM /* * We align everything to a page boundary so we can * free it after init has commenced and TCM contents have * been copied to its destination. */ .tcm_start : { //.tcm_start는 Instruction으로 시작 . = ALIGN(PAGE_SIZE); //PAGE SIZE 할당 __tcm_start = .; //__tcm_start : . 현재 Address 할당 __itcm_start = .; //__itcm_start : . 현재 Address 할당 (아래참고) } /* * Link these to the ITCM RAM * Put VMA to the TCM address and LMA to the common RAM * and we'll upload the contents from RAM to TCM and free * the used RAM after that. */ .text_itcm ITCM_OFFSET : AT(__itcm_start) // AT(ADDRESS)이므로, .text_itcm을 __itcm_start로 연결 { __sitcm_text = .; // Start ITCM TEXT *(.tcm.text) // ITCM TEXT로 Instruction *(.tcm.rodata) . = ALIGN(4); // ALIGN 2의 지수로만 할당(공백할당) __eitcm_text = .; // End ITCM TEXT } /* * Reset the dot pointer, this is needed to create the * relative __dtcm_start below (to be used as extern in code). */ . = ADDR(.tcm_start) + SIZEOF(.tcm_start) + SIZEOF(.text_itcm); // 현재 Address를 변경 사이즈기반 .dtcm_start : { // .tcm_start 뒤에 .dtcm_start 구성 (현재 Address 할당) __dtcm_start = .; } /* TODO: add remainder of ITCM as well, that can be used for data! */ .data_dtcm DTCM_OFFSET : AT(__dtcm_start) // AT(ADDRESS)이므로, .data_dtcm을 __dtcm_start 연결 { . = ALIGN(4); // 공백할당 2의 지수로만 가능 __sdtcm_data = .; // Start DTCM Data *(.tcm.data) // TCM Data . = ALIGN(4); __edtcm_data = .; // End DTCM Data } /* Reset the dot pointer or the linker gets confused */ . = ADDR(.dtcm_start) + SIZEOF(.data_dtcm); // 사이즈 측정하여 현재 Address 변경 /* End marker for freeing TCM copy in linked object */ .tcm_end : AT(ADDR(.dtcm_start) + SIZEOF(.data_dtcm)){ // .tcm_end에 itcm 과 dtcm 끝나는 곳으로 설정 . = ALIGN(PAGE_SIZE); __tcm_end = .; } #endif
- Davinci Deep Sleep Source (TCM이용)
소스의 내용은 Sleep할때는 DRAM을 Self Refresh로 변경하여 Deep Sleep으로 가며,
깨어날때는 DRAM을 사용할 수 없으니, TCM기반의 ISR로 SDRAM 설정변경해주는고 원래대로 돌아가는 방식
https://www.mail-archive.com/davinci-linux-open-source@linux.davincidsp.com/msg04407.html
http://elixir.free-electrons.com/linux/v3.19.7/source/kernel/irq/manage.c
http://elixir.free-electrons.com/linux/v3.19.7/ident/setup_irq
http://elixir.free-electrons.com/linux/v3.19.7/source/include/linux/interrupt.h#L128
https://free-electrons.com/docs/
2. 특정 Address에 원하는 Data 넣기
variable attribute 와 Linker script를 이용하여, 본인이 원하는 위치에 데이타를 저장이 가능하다.
- setup_irq
http://elixir.free-electrons.com/linux/v3.19.7/source/kernel/irq/manage.c
http://elixir.free-electrons.com/linux/v3.19.7/ident/setup_irq
- request_irq
http://elixir.free-electrons.com/linux/v3.19.7/source/include/linux/interrupt.h#L128
https://free-electrons.com/docs/
- IRQ Proc 정보 등록
2. 특정 Address에 원하는 Data 넣기
variable attribute 와 Linker script를 이용하여, 본인이 원하는 위치에 데이타를 저장이 가능하다.
- 저장할 Data를 Code에 Variable Attribute를 이용하여 Section 선언
unsigned char data[48] __attribute__((section(".mySection"))) = {0};
- Variable Attribute 와 같이 Linker Script 수정
SECTIONS //SECTIONS Command로 나만의 Region 만들고 이를 Memory 내에 구성된 이름에 할당
{
.mySegment 0x80200000 :
{
KEEP(*(.mySection))
}
}
SECTIONS Command
http://korea.gnu.org/manual/release/ld/ld-mahajjh/ld_3.html#SEC18- MPU의 예제구성
MPU의 경우는 아래와 같이 MEMORY Layout이 정의되어있으므로, 이 부분 확인
상위내용
https://stackoverflow.com/questions/4067811/how-to-place-a-variable-at-a-given-absolute-address-in-memory-with-gcc
MEMORY //MEMORY Command기반으로 각 Segment/Name 정의 (주소,길이,RWX) { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K // RAM Segment (Read and Write and Excute) FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K // FLASH Segment (Read and Excute) } SECTIONS { .... // 다른 Segment로 구성하고 나의 영역만들고, 이를 FLASH Segment/Name 할당해서 연결 .mySegment 0x80200000 : { KEEP(*(.mySection)) // 상위소스에서 __attribute__를 이용하여 이곳에 할당 } >FLASH }
MEMORY Command
https://stackoverflow.com/questions/4067811/how-to-place-a-variable-at-a-given-absolute-address-in-memory-with-gcc
댓글 없음 :
댓글 쓰기