2009-12-31 6 views
5

Windows에서 C 언어를 사용하고 있습니다. 이 질문은 이전에 What happens to identifiers in a program?의 일부였습니다. 나는 그것을 줄이려고 실패했다. 질문들. 이것은 독립 실행 형 쿼리입니다 (이전 질문에 의존하지 않음)링커 작업이 명확하지 않습니다.

링크 할 항목이없는 경우 (즉, 라이브러리를 사용하고 있지 않다면 사용하지 않을 것입니다.) 링커가 변경됩니다. 어셈블러의 객체 코드 출력? 그렇다면 무엇이 변화합니까?

링커도 일부 메모리 매핑 작업을 수행한다고 들었습니다. 나는 어떻게 이해하지 못한다. 이 프로그램은 제조 단계에 있습니다. 링커는 어떻게 메모리에 매핑 될 수 있습니까? 어떻게 생겼을까요? LINKER의 기능은 모두 무엇입니까?

사람들이 "재배치", "주소 바인딩"을 참조 할 때. 나는 그들이 의미하는 바를 실제로 얻지 못한다. 그것은 무엇입니까 & 그 목적은 무엇입니까?

일부 디버거는 다음과 같은 정보를 표시합니다. 호출 스택 : 0xfffef32, 0xf3234fe 등. 실행 시간이 맞습니까? 또는 링커의 소위 "메모리 매핑"의 메모리 주소입니까?

사람들이 symbols 또는 symbol table과 같은 것을 참조 할 때. 식별자 (변수 이름, 상수 이름, 함수 이름)를 의미합니까?

인터넷에서 정보를 검색했지만 유용한 정보가 없습니다. 내가 무엇을 검색해야할지 모르겠다. 나는 이것에 대한 큰 책을 읽고 싶지 않다. 그러나 어떤 기사라도 있으면, 개념을 명확하게하는 자습서. 그것은 또한 도움이 될 것입니다.

저는 초보 프로그래머입니다. 따라서 간단하지만 기술적 인 용어로 설명 할 수 있으면 좋을 것입니다.

+0

사용중인 언어와 링커를 지정하면 도움이됩니다. 다른 링커는 약간 다른 일을 할 수 있습니다. –

답변

1

이 토론에서는 C와 함께 작업하겠습니다.

C 프로그램이 적어도 일부 라이브러리 함수를 참조하는 경우는 거의 없습니다. 따라서 코드가 하나의 모듈 (파일)에있을지라도 일반적으로 라이브러리 함수에 대한 참조가있을 것입니다. 컴파일 된 형식의 프로그램에서 이러한 참조는 외부 참조 테이블, 즉 텍스트 형식의 이름이 프로그램에서 외부 주소를 참조하려는 위치와 함께 나타나는 테이블에 있습니다.

링커의 임무는 하나의 파일에있는 프로그램을 하나의 파일에 연결하여 사용하는 다른 모듈과 연결 한 다음 한 모듈의 외부 정의를 다른 모듈의 외부 참조와 일치시키는 것입니다. 즉, 호출과 같이 앱과의 모든 상호 참조를 패치하는 것입니다 올바른 주소를 누르십시오.

외부 모듈을 참조하지 않더라도 링크는 코드의 일부 상대 참조를 절대 코드로 변환해야 할 수 있습니다. 즉 일단 파일에서 코드가 어디에 있는지 알게되면 정확한 최종 주소를 사물에 할당 할 수 있습니다.

4

소스 파일을 컴파일 할 때 대개 컴파일러/어셈블러가 여러 섹션으로 나눕니다. 가상의 예를 들어 다음과 같은 섹션이 사용되는 것을 상상 :

  • 는 .text가 - 일정 데이터
  • .DATA을 포함 - -/쓰기 초기화 된 데이터
  • 에게 읽어 포함 .CONST는
  • 모든 실행 코드를 포함 .bss - 초기화되지 않은 데이터 읽기/쓰기가 포함됩니다.

단일 소스 파일에서 컴파일러/어셈블러는 적절한 항목을 적절한 섹션에 할당하고 0에서 시작하는 섹션에서 오프셋을 사용하는 기호를 제공합니다. 예를 들어

는 :

int i; 
const j = 3; 
int k = 4; 
int l; 
int main() 
{ 
return 1; 
} 

이 다음 심볼 테이블 초래할 수 : 오브젝트 파일에서

Symbol Section Offset 
i  .bss 0 
j  .const 0 
k  .data 0 
l  .bss 4 
main .text 0 

심볼 테이블 외에, 각 섹션의 데이터가 유지 될 수있다 . 이 예제에서 .text 섹션은 "return 1"에 대한 객체 코드를 포함하고 const 섹션에는 3을 포함하고 데이터 섹션에는 4가 포함됩니다. 객체 파일에는 .bss 섹션이있을 필요가 없습니다. 초기화되지 않았습니다.

링커가 수행해야 할 첫 번째 작업은 입력 개체 파일의 모든 섹션을 연결하고 이에 따라 심볼 오프셋을 조정하는 것입니다.

이제 우리는 "재배치"또는 "주소 바인딩"을 얻었습니다. 가상 시스템에서 실행 코드가 0x1000 주소에서 시작한다고 가정 해 봅시다. 프로그램의 데이터 섹션이 실행 코드 뒤에 짝수 페이지 경계에서 시작되기를 원한다고 가정 해 봅시다. 링커는 연결된 .text 섹션의 기본 요소로 0x1000을 할당하고 모든 심볼을 조정합니다. 그런 다음 .const, .data 및 .bss 섹션의 기본 섹션을 유사하게 메모리의 적절한 위치에 배치합니다.

때때로 섹션에 기호식 참조가 있습니다. 이러한 참조는 참조 된 기호의 최종 위치를 반영하기 위해 링커에서 업데이트해야합니다. 오브젝트 파일은 각 섹션에서 오프셋 각으로 이동하여 최종 심볼 값을 반영하기 위해이 값을 업데이트합니다

section offset symbol 
.text 0x1234 foo 

링커처럼 "이전 기록"을 포함 할 수 있습니다.

이 모든 작업이 끝나면 결과로 생성되는 "절대"개체 파일을 메모리에로드하고 (적절한 지점에서!) 실행할 수 있습니다.

+0

감사합니다. 그것은 매우 도움이되었습니다. 그러나 기능은 어떨까요? 비슷한 오프셋을 가지고 있습니까? 이 경우 오프셋은 어떻게 계산됩니까? 변수를 참조하거나 함수를 호출해야하는 경우. 어떻게 그럴 수 있습니까? 내가 l = k + 2를 필요로한다면 hypotheticall이라고 말하십시오. 그것은 어떻게합니까? – Alice

+0

나는 가상 시스템에서 실행 코드가 0x1000 주소에서 시작한다고 가정 해 보겠습니다. 실행 가능한 코드 란 무엇을 의미합니까? . 텍스트 섹션? 다른 라이브러리 개체 파일의? 0x1000은 오프셋되어 있습니까? 조금 혼란스러워. - 나는 이것을 이해하지 못했습니다 : '프로그램의 데이터 섹션이 실행 코드 뒤에 짝수 페이지 경계에서 시작되기를 원합니다.' – Alice

+0

예를 들어, 실행 코드는 .text 섹션에 있습니다. (에스). 연결하는 동안 함께 연결됩니다. 함수의 오프셋은 다른 심볼과 마찬가지로 조정됩니다. 비록 .텍스트 오프셋은 0x1000에서 시작될 수 있습니다. 모든 .text 섹션이 결합 될 때 최종 크기는 그보다 훨씬 클 수 있습니다. 코드에 l = k + 2가 포함 된 경우 작업을 수행하는 개체 코드는 l 및 k 주소가 (재배치 레코드로 인해) 최종 계산 값으로 조정됩니다. –

1

대답이 아닙니다. 다만 제안 : "Linkers and Loaders"을 사서 몇 번 읽어보십시오. 놀랍도록 도움이됩니다.

+1

아주 좋은 책 - 저자는 원고를 http://www.iecc.com/linker/ –

+0

"few times"에서 온라인으로 이용할 수있게 만들었습니까 ?? 세상에! 그렇게 어려운가요? – Alice

+1

@Alice 링커는 개념적으로 매우 간단하지만 실제로는 복잡합니다. 그리고 좋은 책은 한번 이상 읽을만한 가치가 있습니다. –

1

링크 할 항목이없는 경우 (즉, 라이브러리를 사용하지 않고 있습니다. 사용하지 않을 것임을 알고 있습니다.) 링커가 어셈블러의 오브젝트 코드 출력을 변경합니까? 그렇다면 무엇이 변화합니까?

항상 일부 초기화 코드를 연결합니다. 이것을 시도하고, 빈 프로그램을 작성하고 링크 한 다음, objdump -d를 사용하여이를 디 어셈블 할 수 있습니다.

나는 링커도 일부 메모리 매핑 작업을한다고 들었습니다. 나는 어떻게 이해하지 못한다. 이 프로그램은 제조 단계에 있습니다. 링커는 어떻게 메모리에 매핑 될 수 있습니까? 어떻게 생겼을까요? LINKER의 기능은 모두 무엇입니까?

각 시스템에는 실행 프로그램이 작동해야하는 메모리 레이아웃이 있습니다. 프로그램의 다른 부분 (최소한 코드, 초기화 된 데이터, 0으로 초기화 된 데이터)을 지정합니다. 링커는 다음 규칙에 따라 실행 파일을 생성해야합니다. Windows 및 Linux.임베디드 시스템에서는 프로그램이 일반적으로 읽기 전용 메모리 (플래시)에 있고 데이터가 RAM에 있고 거기에 마이크로 컨트롤러 유형에 따라 다른 종류의 메모리에 대한 고정 주소 범위가 있습니다.

사람들이 "재배치", "주소 바인딩"을 참조 할 때. 나는 그들이 의미하는 바를 실제로 얻지 못한다. 그것은 무엇입니까 & 그 목적은 무엇입니까?

일반적으로 바인딩이란 이름에 값 (이 경우 함수 또는 전역 변수의 기호에 대한 주소)을 지정하는 것을 의미합니다.

재배치의 경우 일반적으로 두 개 이상의 객체 파일을 서로 연결하며 각 객체 파일은 해당 주소를 시작과 관련된 오프셋으로 지정합니다. 함께 놓으면 각각의 주소 범위가 생기고 링커는 오프셋을 주소 범위에 매핑하여 심볼의 주소를 계산합니다. 이를 재배치라고합니다.

일부 디버거는 다음과 같은 정보를 표시합니다. 호출 스택 : 0xfffef32, 0xf3234fe 등. 실행 시간에 맞습니까? 또는 링커의 소위 "메모리 매핑"의 메모리 주소입니까?

0xfffef32는 일반적으로 메모리의 맨 위에 배치되고 아래쪽으로 커지기 때문에 스택의 일반적인 주소가됩니다. 스택은 반송 주소, 지역 변수 및 실제 함수 매개 변수에 사용됩니다. 이들은 로컬이고 스택 포인터에 상대적인 주소에 저장되기 때문에 일반적으로 링커에서 처리하지는 않지만 컴파일러는 이미 사용할 오프셋을 알고 어셈블리 코드에 넣습니다.

사람들이 기호 나 기호 표 같은 것을 참조 할 때. 식별자 (변수 이름, 상수 이름, 함수 이름)를 의미합니까?

기호 테이블은 기호를 값 (숫자, 오프셋, 주소)에 매핑하는 테이블입니다. 식별자에는 몇 가지 기호가 있지만 다른 용도로는 더 많은 기호가 있습니다. 식별자가 기호가되기 위해 어느 정도 수정 될 수 있습니다. 대부분 이름 충돌을 방지하기 위해 (예 : "_"로 시작).

링커에는 심볼 테이블을 인쇄 할 수있는 --print-map 옵션이 있습니다. 연결에 gcc를 사용한다면 -Wl, --print-map을 사용할 수 있습니다.

이런 종류의 낮은 수준의 기술 자료가 마음에 드시면 임베디드 프로그래밍, 즉 다양한 전기 장치에 사용되는 프로그래밍 마이크로 컨트롤러를 살펴보십시오. Windows와 같은 데스크톱 시스템의 경우 일반적으로 이런 종류의 세부 정보를 볼 필요가 없습니다.

관련 문제