C의 라이브러리에 대해 읽고 있지만 객체 파일이 무엇인지에 대한 설명을 아직 찾지 못했습니다. 다른 컴파일 된 파일과 객체 파일의 실제 차이점은 무엇입니까?
누군가가 인간의 언어로 설명 할 수 있다면 기쁠 것입니다.
C의 라이브러리에 대해 읽고 있지만 객체 파일이 무엇인지에 대한 설명을 아직 찾지 못했습니다. 다른 컴파일 된 파일과 객체 파일의 실제 차이점은 무엇입니까?
누군가가 인간의 언어로 설명 할 수 있다면 기쁠 것입니다.
답변:
객체 파일은 컴파일 단계의 실제 출력입니다. 주로 기계 코드이지만 링커가 작동하는 데 필요한 기호뿐만 아니라 어떤 기호가 들어 있는지 확인할 수있는 정보가 있습니다. 참고로 "기호"는 기본적으로 전역 객체, 함수 등의 이름입니다.
링커는 이러한 모든 객체 파일을 가져와 결합하여 하나의 실행 파일을 만듭니다 (예 : 중복되거나 정의되지 않은 심볼이 없다고 가정). 명령 줄 옵션을 사용하여 "컴파일 만"하도록 지시하지 않으면 많은 컴파일러가이 작업을 수행합니다 (읽기 : 링커 자체 실행). ( -c
일반적인 "컴파일 만하고 링크하지 마십시오"옵션입니다.)
오브젝트 파일은 컴파일 된 파일 자체입니다. 둘 사이에는 차이가 없습니다.
실행 파일은 Object 파일을 연결하여 형성됩니다.
객체 파일에는 CPU가 이해할 수있는 저수준 명령어가 포함되어 있습니다. 이것이 기계 코드라고도하는 이유입니다.
이 낮은 수준의 기계어 코드는 어셈블리 언어를 사용하여 직접 작성한 다음 어셈블러를 사용하여 어셈블리 언어 코드 (영어로 표시)를 기계 언어 (16 진수로 표시)로 처리 할 수있는 명령어의 이진 표현입니다.
다음은 C와 같은 고급 언어 코드의이 프로세스에 대한 일반적인 고급 흐름입니다.
-> 전 처리기 통과
-> 여전히 C로 최적화 된 코드를 제공
-> 컴파일러 통과
-> 어셈블리 코드를 제공
-> 어셈블러 통과
-> 객체 파일에 저장된 기계 언어로 코드를 제공
-> 링커 통과
-> 실행 파일을 가져옵니다.
이 흐름에는 몇 가지 변형이있을 수 있습니다. 예를 들어 대부분의 컴파일러는 어셈블러를 거치지 않고 기계어 코드를 직접 생성 할 수 있습니다. 마찬가지로, 그들은 당신을 위해 전처리를 할 수 있습니다. 그럼에도 불구하고 더 나은 이해를 위해 구성 요소를 분해하는 것이 좋습니다.
3 가지 종류의 객체 파일이 있습니다.
실행 가능한 객체 파일을 형성하기 위해 링크 타임에 다른 재배치 가능한 객체 파일과 결합 할 수있는 형태로 기계 코드를 포함합니다.
a.c
소스 파일 이있는 경우 GCC로 오브젝트 파일을 작성하려면 다음을 실행해야합니다.
gcc a.c -c
전체 프로세스는 다음과 같습니다. 전 처리기 (cpp)는 ac를 통해 실행됩니다. 출력 (여전한 소스)은 컴파일러 (cc1)로 공급됩니다. 출력 (어셈블리)은 어셈블러 (as)로 공급되어을 생성합니다 relocatable object file
. 이 파일에는 객체 코드 및 링크 (및 -g
사용 된 경우 디버깅 ) 메타 데이터가 포함되며 직접 실행 가능하지 않습니다.
로드시 또는 런타임에 동적으로로드 할 수있는 특수 유형의 재배치 가능 오브젝트 파일. 공유 라이브러리는 이러한 종류의 개체의 예입니다.
로더에 의해 메모리에 직접로드되고 (예 : execve ) 나중에 실행될 수있는 머신 코드를 포함합니다 .
여러 개에서 링커를 실행 한 결과 relocatable object files
는 executable object file
입니다. 링커는 모든 동일한 유형의 입력 섹션 (예 :) .data
을 동일한 유형의 출력 섹션 에 병합하여 명령 줄에서 왼쪽에서 오른쪽으로 모든 입력 개체 파일을 병합합니다 . 그것은 사용 symbol resolution
하고 relocation
.
static library
입력 개체에서 참조되는 함수 에 대한 링크 는 최종 실행 파일로 복사됩니다. 함께 dynamic libraries
심볼 테이블 대신 생성되는 라이브러리의 기능 / 전역으로 연결하는 동적 수있게된다. 따라서 결과는 라이브러리에 따라 부분적으로 실행 가능한 오브젝트 파일입니다. 라이브러리가 존재하지 않으면 파일을 더 이상 실행할 수 없습니다.
연결 프로세스는 다음과 같이 수행 할 수 있습니다.
ld a.o -o myexecutable
명령 : gcc a.c -o myexecutable
1 지점과 3 지점에서 언급 된 모든 명령 을 호출합니다 (cpp-> cc1-> as-> ld 1 )
1 : 실제로는 ld의 래퍼 인 collect2입니다.