2009-04-16 3 views
5

Windows 호스트에서 RVDS 컴파일러를 사용하여 * .o 객체 코드 파일 (C 소스 코드)을 사용하여 공유 라이브러리 (* .so)를 만들었습니다.공유 라이브러리에서 심볼을 내보내는 방법

나는 (리눅스 호스트에 팔 대상에 대한 GCC를 사용하여) 응용 프로그램이 공유 객체를 연결하고 실행에 세그먼트 오류를 ​​생성하는 실행 파일을 얻을 수 있습니다. (나는 내가 그것을 디버깅해야 알아!)

대신 공유 라이브러리 만들기, 같은 소스 파일로 정적 라이브러리를 만든 다음 응용 프로그램과 연결 한 다음 응용 프로그램을 실행하면 예상대로 작동합니다.

그래서 제 질문은 다음과 같습니다 : -

  1. 연결된 때 나는 그것이 잘 작동하도록 일부 구조를 사용하여 내 소스 파일에 명시 적으로 심볼 (함수 응용 프로그램에 수출) 또는 다른 기호를 수출해야합니까 신청서와 함께? 필요한 것은 무엇이며 어떻게해야합니까?

  2. 공유 라이브러리는 어떻게 작동합니까? 즉, 함수가로드되고 실행되는 주소는 라이브러리가 생성 될 때 라이브러리에 제공됩니다. 응용 프로그램 (main())은 라이브러리 함수가 실행될 주소를 어떻게 해석합니까?

  3. 정적 라이브러리는 어떻게 작동합니까? 즉 정적 라이브러리의 경우 주소 지정 및 해결 방법은 어떻게됩니까?

감사합니다.

1) 아니, 당신은 아무것도 할 필요가 없습니다 :

답변

11

이것은 리눅스에서 작동하는 방법이다. 그러나 gcc -fvisibility 명령 줄 인수를 사용하여 내보내기 변수를 제한하고 visibility 특성을 사용하여 내 보낸 항목에 명시 적으로 플래그를 지정할 수 있습니다.

2) 실행 파일에는 가져 오는 모든 기능의 테이블 (기본 표시가있는 모든 기능)이 있습니다. 로더/링커는 실행하기 직전에 라이브러리를로드하고이 테이블을 채울 주소를 선택합니다. 이러한 함수에 대한 호출은 간접 호출입니다. (이것은 공유 객체에도 적용됩니다.) 3) 정적 링크는 링크 타임 (컴파일 후)에 수행됩니다. 실제 주소는 어셈블리에서 대체되며 직접 호출입니다.

참고 : PIC (position independent code)라는 것이 있습니다. AFAIK는 동일한 공유 객체에서 데이터/함수에 대한 참조를 다루므로 링커는 라이브러리를로드 할 때 라이브러리의 코드 중 절반을 덮어 쓸 필요가 없습니다. 자신의 데이터. 실험 해 볼 수도 있습니다.

0

충돌의 원인에 대해 아십니까?

공유 라이브러리를 동적으로로드하는 경우 (예 : dlopen()을 통해) 라이브러리가로드되지 않았을 때 라이브러리가로드되었다고 가정하고 null 포인터를 통해 함수를 실행하려고한다고 가정 할 수 있습니다.

+0

@Jonathan : dlopen() 호출을 사용하여 공유 라이브러리를로드하지 않습니다. – goldenmean

+0

OK - 아이디어가 없습니다. 나는 유닉스/리눅스에 대해 더 잘 알고있다. 나는 더 많은 도움이 될지도 모른다. –

3
  1. 당신은 그것을 기본적으로 모든 심볼을 수출로, gcc와 기호를 내보낼 필요가 없습니다; 그러나 RVDS는 동일한 작업을 수행 할 수도 그렇지 않을 수도 있습니다. RVDS 컴파일러 설명서를 확인하십시오 ('Relocatable ELF'출력으로 구성 해보십시오)?)

  2. 런타임시 기본 주소가 결정되므로 Linux의 공유 라이브러리는 재배치가 가능해야합니다. 위치 독립적 코드를 생성하는 것이 이상적입니다. 라이브러리를 재배치하는 데 필요한 작업량이 줄어들 기 때문입니다. 라이브러리를 재배치 할 수없는 경우 이 충돌합니다 (즉, 동적 라이브러리를 만들기 전에 오브젝트 파일에서 재배치 정보를 제거하지 마십시오). 기호는 기본 주소가 선택되고 내부 참조가 재배치 된 후 런타임에 주소로 해석됩니다.

  3. 정적 라이브러리에서는 모든 심볼 해상도, 재배치 및로드 주소 할당이 컴파일 타임에 발생합니다.

필자의 추측에 따르면 컴파일러가 내놓은 코드는 런타임에 재배치되지 않습니다. 그래도 정적 라이브러리를 손상시키지 않으면 어떻게 될지 미스터리예요 ...

정적 라이브러리와 공유 라이브러리를 RVDS에서 직접 생성하는 경우 그 정적 라이브러리를 변환하려고 시도하는 것이 좋습니다

gcc -shared -o libfoo.so libfoo.a 

이렇게하면 RVDS의 공유 라이브러리 링커 (또는 해당 구성)가 손상 될 수 있습니다.

관련 문제