리눅스 커널 코드를 빌드하면 vmlinux란 파일이 추출됩니다.
바이너리 유틸리티를 활용하면 vmlinux에서 여러 디버깅 정보 확인을 할 수 있는데요.
아래 컨피그를 추가하면 vmlinux 심볼 테이블에 소스 코드 정보가 추가됩니다.
diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig
index 96fbcc6..961829b 100644
--- a/arch/arm/configs/bcm2709_defconfig
+++ b/arch/arm/configs/bcm2709_defconfig
@@ -31,6 +31,7 @@ CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
+CONFIG_DEBUG_INFO=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_BLK_DEV_THROTTLING=y
위와 같이 컨피그 코드 수정 후 build_kernel.sh 파일을 실행시켜 생긴 .config 파일을 열어보면 CONFIG_DEBUG_INFO=y 컨피그가 실제 켜져 있네요.
bald.candy~/src/raspberry_kernel/out$ vi .config
5459 # Compile-time checks and compiler options
5460 #
5461 CONFIG_DEBUG_INFO=y
5462 # CONFIG_DEBUG_INFO_REDUCED is not set
그런데 컴파일 도중 아래와 같은 에러 메세지와 함께 빌드가 중지됩니다.
lib/raid6/neon8.c: In function ‘raid6_neon8_gen_syndrome_real’:
lib/raid6/neon8.c:158:1: internal compiler error: in dwarf2out_frame_debug_adjust_cfa, at dwarf2cfi.c:1078
}
^
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://bugs.launchpad.net/gcc-linaro> for instructions.
make[3]: *** [lib/raid6/neon8.o] Error 1
make[3]: *** Waiting for unfinished jobs....
lib/raid6/neon4.c: In function ‘raid6_neon4_gen_syndrome_real’:
lib/raid6/neon4.c:114:1: internal compiler error: in dwarf2out_frame_debug_adjust_cfa, at dwarf2cfi.c:1078
}
^
소스 정보가 포함된 vmlinux 파일을 얻는 게 목적이므로 아래 패치를 적용하고 다시 빌드합니다.
diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile
index 3057011..69f563e 100644
--- a/lib/raid6/Makefile
+++ b/lib/raid6/Makefile
@@ -5,7 +5,7 @@ raid6_pq-y += algos.o recov.o tables.o int1.o int2.o int4.o \
raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o mmx.o sse1.o sse2.o avx2.o avx512.o recov_avx512.o
raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o
-raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o neon4.o neon8.o
+raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o
raid6_pq-$(CONFIG_TILEGX) += tilegx8.o
raid6_pq-$(CONFIG_S390) += s390vx8.o recov_s390xc.o
위 패치를 적용하고 난 후 out 폴더에 vmlinux가 제대로 생성됩니다.
바이너리 유틸리티 사용
raspberry_tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-objdump 폴더에 위치한 arm-linux-gnueabihf-objdump 파일을 out 폴더에 복사합니다.
bald.candy~/src/raspberry_kernel/out$ cp ~/bin/raspberry_tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-objdump .
bald.candy:~/src/raspberry_kernel/out$
아래 명령어를 치면 arm-linux-gnueabihf-objdump 바이너리 유틸리티 옵션을 확인할 수 있습니다.
austindh.kim@~/src/raspberry_kernel/out$ ./arm-linux-gnueabihf-objdump
Usage: ./arm-linux-gnueabihf-objdump <option(s)> <file(s)>
Display information from object <file(s)>.
At least one of the following switches must be given:
-a, --archive-headers Display archive header information
-f, --file-headers Display the contents of the overall file header
-p, --private-headers Display object format specific file header contents
-P, --private=OPT,OPT... Display object format specific contents
-h, --[section-]headers Display the contents of the section headers
-x, --all-headers Display the contents of all headers
-d, --disassemble Display assembler contents of executable sections
-D, --disassemble-all Display assembler contents of all sections
-S, --source Intermix source code with disassembly
-s, --full-contents Display the full contents of all sections requested
-g, --debugging Display debug information in object file
-e, --debugging-tags Display debug information using ctags style
-G, --stabs Display (in raw form) any STABS info in the file
-W[lLiaprmfFsoRt] or
--dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
=frames-interp,=str,=loc,=Ranges,=pubtypes,
=gdb_index,=trace_info,=trace_abbrev,=trace_aranges,
=addr,=cu_index]
Display DWARF info in the file
-t, --syms Display the contents of the symbol table(s)
-T, --dynamic-syms Display the contents of the dynamic symbol table
-r, --reloc Display the relocation entries in the file
-R, --dynamic-reloc Display the dynamic relocation entries in the file
@<file> Read options from <file>
-v, --version Display this program's version number
-i, --info List object formats and architectures supported
-H, --help Display this information
아래 리다이렉트 명령어로 결과 파일을 dump_kernel_code.c에 저장합니다.
austindh.kim@~/src/raspberry_kernel/out$ ./arm-linux-gnueabihf-objdump -d -S vmlinux > dump_kernel_code.c
이제 dump_kernel_code.c 파일을 열어서 start_kernel 코드를 검색하면 어셈블리와 소스코드를 함께 볼 수 있습니다.
80b00970 <start_kernel>:
ioremap_huge_init();
kaiser_init();
}
asmlinkage __visible void __init start_kernel(void)
{
80b00970: e1a0c00d mov ip, sp
80b00974: e92ddff0 .word 0xe92ddff0
80b00978: e24cb004 sub fp, ip, #4
80b0097c: e24dd01c sub sp, sp, #28
char *command_line;
char *after_dashes;
set_task_stack_end_magic(&init_task);
80b00980: e59f0344 .word 0xe59f0344
80b00984: ebd8655d bl 80119f00 <set_task_stack_end_magic>
smp_setup_processor_id();
80b00988: eb000c3b .word 0xeb000c3b
/*
* Set up the the initial canary ASAP:
*/
boot_init_stack_canary();
cgroup_init_early();
>>>
ffffff80080d58c0 <_do_fork>:
unsigned long stack_start,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr,
unsigned long tls)
{
ffffff80080d58c0: a9b87bfd stp x29, x30, [sp,#-128]!
ffffff80080d58c4: 910003fd mov x29, sp
ffffff80080d58c8: a90153f3 stp x19, x20, [sp,#16]
ffffff80080d58cc: a9025bf5 stp x21, x22, [sp,#32]
ffffff80080d58d0: a90363f7 stp x23, x24, [sp,#48]
ffffff80080d58d4: a9046bf9 stp x25, x26, [sp,#64]
ffffff80080d58d8: aa0003f3 mov x19, x0
ffffff80080d58dc: aa1e03e0 mov x0, x30
ffffff80080d58e0: aa0103f4 mov x20, x1
ffffff80080d58e4: f0005e96 adrp x22, ffffff8008ca8000 <page_wait_table+0x1500>
ffffff80080d58e8: aa0203f8 mov x24, x2
ffffff80080d58ec: aa0303f9 mov x25, x3
ffffff80080d58f0: aa0403f5 mov x21, x4
ffffff80080d58f4: 97ff129a bl ffffff800809a35c <_mcount>
ffffff80080d58f8: 911a22c0 add x0, x22, #0x688
struct completion vfork;
struct pid *pid;
struct task_struct *p;
int trace = 0;
ffffff80080d58fc: 52800017 mov w23, #0x0 // #0
...
if (!(clone_flags & CLONE_UNTRACED)) {
ffffff80080d590c: 37b80113 tbnz w19, #23, ffffff80080d592c <_do_fork+0x6c>
if (clone_flags & CLONE_VFORK)
ffffff80080d5910: 36700a53 tbz w19, #14, ffffff80080d5a58 <_do_fork+0x198>
ffffff80080d5914: 52800400 mov w0, #0x20 // #32
trace = PTRACE_EVENT_VFORK;
ffffff80080d5918: 52800057 mov w23, #0x2 // #2
ffffff80080d591c: d5384101 mrs x1, sp_el0
*
* Returns %true if @event is enabled, %false otherwise.
*/
static inline bool ptrace_event_enabled(struct task_struct *task, int event)
{
return task->ptrace & PT_EVENT_FLAG(event);
ffffff80080d5920: b9403021 ldr w1, [x1,#48]
trace = PTRACE_EVENT_CLONE;
else
trace = PTRACE_EVENT_FORK;
if (likely(!ptrace_event_enabled(current, trace)))
trace = 0;
ffffff80080d5924: 6a01001f tst w0, w1
ffffff80080d5928: 1a9f12f7 csel w23, w23, wzr, ne
'시스템 소프트웨어 개발을 위한 Arm 아키텍처의 구조와 원리' 카테고리의 다른 글
[ARM] tst 명령어를 실행하면 ARM CPSR 레지스터가 어떻게 변경될까? (0) | 2023.06.09 |
---|---|
[Linux][ARM] Coprocessor(코프로세서) Assembly (0) | 2023.06.09 |
arm32 - Unwind Idx/prolog 소개 (0) | 2023.06.09 |
ARM64- Stack Push Userspace -> Kernel Space 코드리뷰 (0) | 2023.06.09 |
ARM64 - 프로세스(Process) preempt_disable(), preemption 스케줄(Schedule) 조건 분석 (0) | 2023.06.09 |