Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

8179
1390
307630


[리눅스커널][디버깅] T32(Trace32)로 vmlinux 로딩해 시스템 구경하기 3. 커널 디버깅과 코드 학습

T32 시작 명령어 

T32 시뮬레이터를 열고 다음 명령어를 입력합시다.
sys.cpu cortexa7
sys.up  

대부분 ARM32 아키텍처는 위 명령어로 T32가 초기화됩니다.

T32 명령어로 시스템 점검하기

먼저 커널 섹션 정보를 보겠습니다.
y.l.sec
__________address________|path\section___________________________|acc|init|physical
     P:00000000--0000001F|\\vmlinux\.vectors                     |R-X|L-  |
     P:00001000--000012BF|\\vmlinux\.stubs                       |R-X|L-  |
     P:C0008000--C00081FF|\\vmlinux\.head.text                   |R-X|L-  |
     P:C0008200--C065190F|\\vmlinux\.text                        |R-X|L-  |
     P:C0651910--C0651937|\\vmlinux\.fixup                       |R-X|L-  |
     D:C0652000--C086A30F|\\vmlinux\.rodata                      |R--|L-  |
     D:C086A310--C086B71F|\\vmlinux\.pci_fixup                   |R--|L-  |
     D:C086B720--C086B72B|\\vmlinux\.builtin_fw                  |R--|L-  |
     D:C086B72C--C08741E3|\\vmlinux\__ksymtab                    |R--|L-  |
     D:C08741E4--C087ABEB|\\vmlinux\__ksymtab_gpl                |R--|L-  |
     D:C087ABEC--C087F147|\\vmlinux\__kcrctab                    |R--|L-  |
     D:C087F148--C088264B|\\vmlinux\__kcrctab_gpl                |R--|L-  |
     D:C088264C--C08A739F|\\vmlinux\__ksymtab_strings            |R--|L-  |
     D:C08A73A0--C08A7D0F|\\vmlinux\__param                      |R--|L-  |
     D:C08A7D10--C08A7FFF|\\vmlinux\__modver                     |R--|L-  |
     D:C08A8000--C08A903F|\\vmlinux\__ex_table                   |R--|L-  |
     P:C08A9040--C08A9063|\\vmlinux\.notes                       |R-X|L-  |
     P:C08AA2E0--C08DDB9B|\\vmlinux\.init.text                   |R-X|L-  |
     P:C08DDB9C--C08E04DF|\\vmlinux\.exit.text                   |R-X|L-  |
     D:C08E04E0--C08E074F|\\vmlinux\.init.proc.info              |R--|L-  |
     D:C08E0750--C08E081F|\\vmlinux\.init.arch.info              |R--|L-  |
     D:C08E0820--C08E0867|\\vmlinux\.init.tagtable               |R--|L-  |
     D:C08E0868--C08E0B2B|\\vmlinux\.init.pv_table               |R--|L-  |
     D:C08E0B40--C08EDCD3|\\vmlinux\.init.data                   |RW-|L-  |
     D:C08EE000--C092E81F|\\vmlinux\.data                        |RW-|L-  |
     D:C092F000--C0930FFF|\\vmlinux\.data..page_aligned          |RW-|L-  |
     D:C0931000--C096B74B|\\vmlinux\.bss                         |RW-|--  |

전형적인 ARM32 비트 리눅스 섹션입니다.   

linux_banner로 커널 빌드 정보를 보겠습니다.
v.v %s linux_banner
  (static char [135]) linux_banner = "Linux version 4.1.18 (nsg@nsg-W3x0ET) (gcc version 5.3.1 20160113 (Linaro GCC 5.3-2016.02) ) #10 PREEMPT Tue Mar 12 11:04:01 KST 2019.

커널 버전은 4.1.18이고 3/12일 오전 11:04에 커널 빌드가 됐습니다.   


이번엔 스케줄러 클래스를 볼까요?
v.v %h %t %y stop_sched_class
  (static struct sched_class) stop_sched_class = (
    (struct sched_class *) next = 0xC06565DC = dl_sched_class -> (
      (struct sched_class *) next = 0xC0656594 = rt_sched_class -> (
        (struct sched_class *) next = 0xC0656548 = fair_sched_class -> (
          (struct sched_class *) next = 0xC0656500 = idle_sched_class -> (
            (struct sched_class *) next = 0x0 = ,
            (void (*)()) enqueue_task = 0x0 = ,
            (void (*)()) dequeue_task = 0xC005CC9C = dequeue_task_idle,
            (void (*)()) yield_task = 0x0 = ,
            (bool (*)()) yield_to_task = 0x0 = ,
            (void (*)()) check_preempt_curr = 0xC005CC88 = check_preempt_curr_idle,
            (struct task_struct * (*)()) pick_next_task = 0xC005CC00 = pick_next_task_idle,
            (void (*)()) put_prev_task = 0xC005CC24 = put_prev_task_idle,
            (void (*)()) set_curr_task = 0xC005CD0C = set_curr_task_idle,
            (void (*)()) task_tick = 0xC005CC34 = task_tick_idle,
            (void (*)()) task_fork = 0x0 = ,
            (void (*)()) task_dead = 0x0 = ,
            (void (*)()) switched_from = 0x0 = ,
            (void (*)()) switched_to = 0xC005CC78 = switched_to_idle,
            (void (*)()) prio_changed = 0xC005CC68 = prio_changed_idle,
            (unsigned int (*)()) get_rr_interval = 0xC005CC44 = get_rr_interval_idle,
            (void (*)()) update_curr = 0xC005CC58 = update_curr_idle,
            (void (*)()) task_move_group = 0x0 = ),

자체 스케줄러 클래스는 안 보입니다.

스핀락 타입 지역변수를 볼까요?
v.v %all auth_domain_lock
  (static spinlock_t) auth_domain_lock = (
    (struct raw_spinlock) rlock = (
      (arch_spinlock_t) raw_lock = ()))

어라, 스핀락 구조체로 보아 CONFIG_SMP를 안킨 것 같습니다.

이번에는 __irq_svc 레이블을 점검해보겠습니다.
______addr/line|code_____|label__________|mnemonic________________|comment
   NSR:C064F7C0|E24DD044  __irq_svc:      sub     r13,r13,#0x44    ; r13,r13,#68
   NSR:C064F7C4|E31D0004                  tst     r13,#0x4         ; r13,#4
   NSR:C064F7C8|024DD004                  subeq   r13,r13,#0x4     ; r13,r13,#4
...
   NSR:C064F7F0|E59F1038                  ldr     r1,0xC064F830
   NSR:C064F7F4|E1A0000D                  cpy     r0,r13
   NSR:C064F7F8|E28FE000                  adr     r14,0xC064F800
   NSR:C064F7FC|E591F000                  ldr     pc,[r1]
   NSR:C064F800|E1A096AD                  lsr     r9,r13,#0x0D
   NSR:C064F804|E1A09689                  lsl     r9,r9,#0x0D
   NSR:C064F808|E5998004                  ldr     r8,[r9,#0x4]
   NSR:C064F80C|E5990000                  ldr     r0,[r9]
   NSR:C064F810|E3380000                  teq     r8,#0x0          ; r8,#0
   NSR:C064F814|13A00000                  movne   r0,#0x0          ; r0,#0
   NSR:C064F818|E3100002                  tst     r0,#0x2          ; r0,#2
   NSR:C064F81C|1B000004                  blne    0xC064F834       ; svc_preempt

svc_preempt 레이블를 브랜치하니 preempt 컨피그는 켜져 있습니다. 전형적인 상용 리눅스 시스템입니다.

심보를 보니 omap으로 시작하는 함수들이 많이 보입니다.
y.l.line omap44xx_prm_init
__________address________|module__________________________________|source____________________________________________|line
     P:C08B8910--C08B891B|\\vmlinux\prm44xx                       |.ome\nsg\myir-kernel\arch\arm\mach-omap2\prm44xx.c|\762--0

arch\arm\mach-omap2 폴더에 위치한 코드를 쓰고 있습니다.

덧글

댓글 입력 영역