문제

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

이 공유 객체를 응용 프로그램과 연결합니다 (사용 gcc Linux 호스트의 ARM 대상의 경우) 및 실행 파일을 얻으십시오. (나는 그것을 디버깅해야한다는 것을 안다!)

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

그래서 내 질문은 다음과 같습니다.

  1. 신청서와 연결될 때 제대로 작동하도록 일부 구조물을 사용하여 내 소스 파일에서 기호 (응용 프로그램으로 내보낸 기능) 또는 다른 기호를 내보내야합니까? 무엇이 필요하고 어떻게해야합니까?

  2. 공유 라이브러리는 어떻게 작동합니까?, 즉, 기능이로드되고 실행 될 주소는 라이브러리를 만들 때 라이브러리에 제공 될 것입니다. 응용 프로그램은 어떻게합니까 ( main() ) 라이브러리 기능을 실행할 주소를 해결합니까?

  3. 정적 라이브러리는 어떻게 작동합니까? 즉, 정적 라이브러리의 경우이 주소 사양과 해결은 어떻게 발생합니까?

도움이 되었습니까?

해결책

이것이 Linux에서 작동하는 방식입니다.

1) 아니, 당신은 아무것도 할 필요가 없습니다. 그러나 GCC로 수출 변수를 제한 할 수 있습니다. -fvisibility 명령 줄 인수 및 가시성 속성으로 내보낸 항목을 명시 적으로 플래그합니다.

2) 실행 파일에는 가져 오는 모든 기능의 테이블이 있습니다 (이 기능은 모두 기본적으로 가시성이있는 기능입니다). 로더/링커는 라이브러리를로드하기위한 주소를 선택하고 실행 직전 에이 테이블을 채우고 해당 함수에 대한 호출은 간접 호출입니다. (이것은 공유 객체에도 적용됩니다)

3) 정적 연결은 링크 시간 (컴파일 후)에서 수행됩니다. 실제 주소는 어셈블리에서 대체되며 직접 전화입니다.

참고 : PIC (위치 독립 코드)라는 것이 있습니다. AFAIK, 이것은 동일한 공유 객체의 데이터/함수에 대한 참조를 다루므로 링커는 라이브러리를로드 할 때 라이브러리 코드의 절반을 덮어 쓰지 않아도됩니다. 자체 데이터. 당신은 그것을 실험하려고 할 수 있습니다.

다른 팁

  1. 기호를 내보낼 필요가 없습니다 gcc, 기본적으로 모든 기호를 내보내므로; 그러나 RVD는 동일하거나 동일하지 않을 수도 있습니다. RVDS 컴파일러 문서를 확인하십시오 (구성 시도재배치 가능한 엘프'출력?)

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

  3. 정적 라이브러리를 사용하면 모든 기호 해상도, 재배치 및 부하 주소 할당이 컴파일 시간에 발생합니다.

내 유일한 추측은 어쨌든, 컴파일러가 출시되는 코드는 런타임에 재배치 할 수 없다는 것입니다. 그래도 정적 라이브러리를 깨지 않고 어떻게 일어날지는 미스터리입니다.

RVD에서 직접 정적 라이브러리와 공유 라이브러리를 생성하는 경우 해당 정적 라이브러리를 공유 라이브러리로 변환하는 것이 옵션입니다.

gcc -shared -o libfoo.so libfoo.a

이것이 도움이되면 RVDS의 공유 라이브러리 링커 (또는 구성)가 고장 났을 것입니다.

사고의 원인에 대해 아는 것이 있습니까?

공유 라이브러리를 동적으로로드하는 경우 (예 : dlopen())는 라이브러리가 그렇지 않은 경우에도로드 된 것으로 가정 한 다음 NULL 포인터를 통해 기능을 실행하려고한다고 가정합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top