sort_main_extable()

Main Exception Table이 정렬되어 있지 않은 경우 정렬한다.

  • Exception Table은 다음 두 가지가 있다.
    • Main Exception Table
    • 각 Driver에서 사용하는 Exception Table
  • 컴파일 타임에 툴에 의해 Exception table을 정렬하고, 툴에 의해 main_extable_sort_needed 변수 값까지 1로 바꿔주면  커널 부트업 처리 시 정렬을 할 필요가 없다.
    • CONFIG_BUILDTIME_EXTABLE_SORT 커널 옵션을 사용하여 빌드 타임에 Exception table을 정렬하게 한다.

 

sort_main_extable-1

 

sort_main_extable()

kernel/extable.c

/* Sort the kernel's built-in exception table */
void __init sort_main_extable(void)
{
        if (main_extable_sort_needed && __stop___ex_table > __start___ex_table) {
                pr_notice("Sorting __ex_table...\n");
                sort_extable(__start___ex_table, __stop___ex_table);
        }      
}

Main 커널에서 사용하는 Exception table을 정렬되어 있지 않은 경우 정렬한다.

 

kernel/extable.c

/* Cleared by build time tools if the table is already sorted. */
u32 __initdata __visible main_extable_sort_needed = 1;

 

sort_main_extable()

kernel/extable.c

void sort_extable(struct exception_table_entry *start,
                  struct exception_table_entry *finish)
{       
        sort(start, finish - start, sizeof(struct exception_table_entry),
             cmp_ex, NULL);
}

Exception table의 시작 부터 끝 까지 정렬한다.

 

cmp_ex()

lib/extable.c

/*      
 * The exception table needs to be sorted so that the binary
 * search that we use to find entries in it works properly.
 * This is used both for the kernel exception table and for
 * the exception tables of modules that get loaded.
 */
static int cmp_ex(const void *a, const void *b)
{       
        const struct exception_table_entry *x = a, *y = b;
        
        /* avoid overflow */
        if (x->insn > y->insn)
                return 1;
        if (x->insn < y->insn)
                return -1;
        return 0;
}

sort_extable() 함수가 ARCH_HAS_SORT_EXTABLE 커널 옵션이 없는 경우 사용할 수 있는 generic한 비교 루틴이다.

  • x86, ia64, sparc, s390, alpha 아키텍처에서는 별도의 구현 루틴이 제공된다.

 

__ex_table

arch/arm/kernel/vmlinux.lds.S

#ifdef CONFIG_DEBUG_RODATA
        . = ALIGN(1<<SECTION_SHIFT);
#endif
        RO_DATA(PAGE_SIZE)

        . = ALIGN(4);
        __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
                __start___ex_table = .;
#ifdef CONFIG_MMU
                *(__ex_table)
#endif
                __stop___ex_table = .;
        }

__ex_table은 .rodata 섹션 뒤에 위치한다.

 

참고

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.