2012-10-28 28 views

답변

27

'?' 이 스택 항목에 대한 정보가 신뢰할 수 없다는 것을 의미합니다.

스택 출력 메커니즘 (구현은 dump_trace() function 참조)은 발견 된 주소가 호출 스택의 유효한 반환 주소임을 증명할 수 없었습니다.

'?' 자체는 printk_stack_address()에 의해 출력됩니다.

스택 항목이 유효 할 수도 있고 유효하지 않을 수도 있습니다. 때로는 단순히 건너 뛸 수도 있습니다. 관련 모듈의 분해를 조사하여 ClearFunctionName+0x88 (또는 해당 위치 바로 앞에있는 x86에서) 함수가 호출되는지 확인하는 것이 도움이 될 수 있습니다. dump_stack() 호출 신뢰도 86에

관한

, 실제로는 print_context_stack()arch/x86/kernel/dumpstack.c에 정의 된 스택을 검사하는 기능. 코드를 살펴보면, 아래에서 설명하겠다.

Linux 시스템에서는 DWARF2 스택 unwind 기능을 사용할 수 없다고 가정합니다 (대부분 OpenSUSE 또는 SLES가 아닌 경우는 그렇지 않습니다). 이 경우 print_context_stack()은 다음을 수행하는 것으로 보입니다.

스택 위치의 주소가 될 수있는 주소 (코드의 'stack'변수)부터 시작합니다. 실제로 로컬 변수의 주소는 dump_stack()입니다.

이 함수는 해당 주소 (while (valid_stack_ptr ...) { ... stack++})를 반복하여 증가시키고 해당 주소가 커널 코드 (if (__kernel_text_address(addr)) ...)의 주소 일 수 있는지 확인합니다. 이렇게하면 함수가 호출 될 때 스택에 푸시 된 함수의 반환 주소를 찾으려고 시도합니다.

물론 반환 주소처럼 보이는 모든 부호없는 long 값이 실제로 반환 주소가되는 것은 아닙니다. 그래서 함수는 그것을 검사하려고합니다. 커널 포인터 (% ebp/% rbp 레지스터는 CONFIG_FRAME_POINTER가 설정된 경우 레지스터가 사용됨)에서 프레임 포인터가 사용되면 함수의 스택 프레임을 탐색하는 데 사용할 수 있습니다. 함수의 반환 주소는 프레임 포인터 바로 위 (즉, %ebp/%rbp + sizeof(unsigned long))에 있습니다. print_context_stack은 정확히 그것을 검사합니다.

'stack'값이 가리키는 스택 프레임이 반환 주소 인 경우이 값은 신뢰할 수있는 스택 항목으로 간주됩니다. ops->addressreliable == 1과 함께 호출되면 결국 printk_stack_address()을 호출하며 신뢰할 수있는 호출 스택 항목으로 값이 출력됩니다. 그렇지 않으면 주소가 신뢰할 수없는 것으로 간주됩니다. 그것은 출력되지만 어쨌든 '?' 앞에 붙었다.

[NB] 프레임 포인터 정보를 사용할 수없는 경우 (예 : 기본적으로 데비안 6 에서처럼) 모든 호출 스택 항목은 이러한 이유로 신뢰할 수 없다고 표시됩니다.

DWARF2 unwinding 지원 (및 CONFIG_STACK_UNWIND 세트 사용)이있는 시스템은 완전히 다른 이야기입니다.

+0

위대한 답변 - 완료하기 위해 한 가지를 놓친다. (나는 아치 코드에서 간접 참조의 수준에 약간 당황 스럽다.) 무엇이 항목을 신뢰할 수 없게 만들까? – qdot

+0

나는 나의 대답을 편집했다. 바라기를, 나의 설명은 너무 혼동하지 않는다. – Eugene

+0

Getting there :) 당신의 대답은 실제로 그것이 작동하는 방법에 대한 나의 의심을 확인합니다 - 약간의 배경 정보를 제공하기 위해 드라이버와 같이 바이너리 블롭 + 래퍼를 업데이트하려고합니다 - 그래서 커널은 실제로 제 자신의 빌드입니다 .. 내가 혼란스러워하고 몇 가지 설명을 원했던 이유는 BLOB 저장소 함수 포인터의 일부 함수가 지역 변수에서 포인터를 사용하여 전체 시스템을 약간 벗어 던지기 때문입니다. '전체적인 또 다른 이야기'를 마무리하십시오 - 특히 주 커널이 DWARF2 일 때 어떻게 작동합니까?하지만 모듈의 일부는 그렇지 않습니다. – qdot