2016년 3월 30일 수요일

파이썬의 라이브러리 NumPy + SciPy _____ 8

==========================================================
이 포스팅은 쓸모 없어진 포스팅입니다.
(NumPy + SciPy ____ 4 ~ NumPy + SciPy ____ 8)
해당 문제점은 Scipy 패키지를 빌드했던 툴(아마도 MS Visual Studio 201x)이 Windows XP를 지원하지 않아서 발생한 것으로 추측하고 있습니다.
이후의 포스팅에서 이 시행착오를 정리할 계획입니다. (아마도 NumPy + SciPy ____ 9)
==========================================================

어차피 우아하게 소스 레벨 디버깅도 물 건너간 상태다.

닥치고 수정 - 실행 , 재수정 - 실행의 무한 반복.

그나마 감 잡히는 부분이 있어서 다행이다.


로드하려는 라이브러리의 경로를 절대 경로로 지정하기 위해서 변환까지 하고, 변환하기 전의 경로를 사용한 부분.

dynload_win.c
pathname이라는 변수 대신에 pathbuf를 쓰는게 맞다고 생각해서 위 처럼 소스를 수정했다.

그리고 다시 빌드하고, 다시 실행해 본 결과,


역시나 같은 결과.

그것도 아니면 대체 뭐가 문제란 말인가?


dynload_win.c
의심이 가는 변수들의 값을 모두 확인하고자, 에러 메시지의 내용을 원하는 변수 값으로 출력하도록 수정했다.

그리고 다시 빌드하고 실행해 본 결과,


위의 함수가 호출될 때, 로드하라고 지정한 라이브러리는 _ufuncs
여기에 경로가 모두 포함된 pathname과 pthbuf는 결과적으로 _ufuncs.pyd를 똑같이 지정하고 있었다.


하지만 내가 알아낸 바에 의하면 _ufuncs.pyd라는 파일 자체를 로드하지 못한 것이 아니라, _ufuncs.pyd에서 필요로 하는 또 다른 DLL인 libifcoremd.dll을 찾지 못했기 때문에 발생한 것이었다.

그리고, 내 짐작엔 소스에서 로드하려고 LoadLibraryEx를 호출하는 이 부분이 바로 libifcoremd.dll를 대상으로 삼고 있을거라 생각했던 것이다.

하지만 그게 아니었다.

어쩌면 당연한거였는지도 모르겠다.

너무나 1차원적으로, 단순하게 생각했던 것이다.

저 메시지로 짐작하건데, _ufuncs.pyd도 라이브러리 이므로 LoadLibraryEx() 함수를 이용해 로딩하는 게 맞지만, OS의 입장에서 본다면, _ufuncs.pyd에서 또 다른 라이브러리의 함수를 사용할 수도 있는 것이고 그렇다면 그에 해당하는 DLL도 또한 로드해야만 제대로 된 작동을 할 수 있을 것이다.

그것이 libifcoremd.dll 이었던 것이다.

그렇다면 libifcoremd.dll은 어디에 명시되어 있을까?
아마도 _ufuncs.pyd에 명시되어 있을 것이다. 그래서 Ollydbg에서 해당 DLL을 찾을 수 없다고 메시지를 보여 줬던 것이리라.

그러면 통상의 DLL 탐색 순서에 따라 libifcoremd.dll을 탐색하고 찾아서 자동으로 로드해 주었으면 좋으련만, 윈도우즈에서는 그렇게까지 하지 않는 모양이다.

어쩌면 _ufuncs.pyd에는 libifcoremd.dll이 명시되어 있지 않을 수도 있고, 단지 libifcoremd.dll에 포함된 함수(프로시져)의 이름만을 명시하고 있을지도 모른다.

그렇다면 OS는 해당 함수를 가지고 있는 DLL이 무엇인지를 모두 뒤져봐야 할 것이고, 이건 너무나도 비효율적일테니, 특별히 자신이 가지 함수 이름을 미리 등록해 놓은 DLL에 대해서만 이런 서비스를 제공해 주는 것일지도 모른다.

(마침 _ufuncs.pyd에서 libifcoremd라는 문자열이 있는지 검색해 보았지만 찾지 못하고 있다. 오히려 Ollydbg가 메시지를 보여준게 신기할 따름.)

그렇다면 애초에 인텔의 이 라이브러리들을 아무 곳이나 PATH가 지정된 곳에 복사해 넣어서는 안되고, regsvr32라는 프로그램을 이용해서 등록해 주는 절차가 필요한 것이 아니었을까?

그렇다면 전에 받아 두었던 인텔의 배포용 라이브러리를 설치하는 것이 가장 좋은 해결책이 될지도 모르겠다.


그래서 당장 실행.
Intel C++ Redistributables for IA32

Intel Fortran Redistributables for IA32

설치 후에 추가된 PATH. 저기에 DLL들이 위치하고 있다.

설치 후에 다시 실행

그러나 이 모든 것을 다시 설치하고도 문제는 여전.
내가 빌드한 파이썬의 바이너리와 DLL을 모두 지우고, 원래 배포버전으로 돌려놓고 시험해도 마찬가지였다.

그럼 정말 이것도 문제가 아니었단 말인가?

틀림없이 libifcoremd.dll이 설치된 것을 확인했는데도?

그래서 다시 Ollydbg에서 _ufuncs.pyd를 불러 보았다.



헉...이번엔 메시지가 달랐다.

이번엔 libifcoremd.dll이 아니라, libmmd.dll이 문제였고, 그것도 해당 DLL 없다는 것이 아니라 특정 함수의 진입점이 없다는 것.

진전은 있지만 굉장히 불길한 예감.

============================================================================
애초에 이문제는 파이썬의 문제가 아니었다.

생각해 보면 NumPy나 SciPy의 문제도 아니었다.

NumPy나 SciPy를 MS-Windows용으로 빌드를 하는 과정에 어떤 툴을 이용했느냐에 따라 필요로하는 라이브러리나 DLL이 달라질 수 있기 때문이다.

친절한 크리스토프 골케씨가 NumPy와 SciPy를 빌드해서 배포해 주셨지만, 거기에 필요한 Intel의 라이브러리에 대한 충고는 깜빡했다고 밖에 볼 수 없다.
=============================================================================

마지막으로 OllyDbg에서 보여준 메시지에 따라 libmmd.dll을 확인해 보았다.

인텔의 배포 라이브러리 중 C++용과 Fortran용 양쪽 모두에 있는 라이브러리이며, 양쪽 라이브러리 모두 libm_sse2_exp2라는 함수의 이름은 존재하고 있었다.

문제는 정말 함수의 이름만 존재하고 진입점이 없다면....이번엔 인텔의 문제?

댓글 2개:

Unknown :

이 글로 인해 저의 프로그램이 실행될 수 있었습니다.
이 글을 포스팅해주셔서 너무나 너무나 너무나 감사드립니다 ㅠㅠㅠㅠ
Redistributable libraries for the Intel® C++ and Visual Fortran Compiler 11.1 for Windows
이 글 덕분에 포트란 재배포 패키지를 다운 받을 수 있었습니다.
그래서 필요한 LIBIFCOREMD.DLL을 다운 받을 수 있었습니다. 진짜 정말 너무 완전 엄청 감사드립니다!!

Re-coder :

제 포스팅 덕을 보셨다니 매우 기쁘네요.
정작 저는 이 포스팅 이후로 나가지 못하고 있는데...ㅠㅠ
혹시 사용하시는 환경(CPU, OS)를 알려주신다면, 저를 포함해서 이 글을 보시는 분들께 도움이 되지 않을까 싶습니다.