레이블이 Bug인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Bug인 게시물을 표시합니다. 모든 게시물 표시

2016년 3월 21일 월요일

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

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

정말 정말 궁금했습니다.
왜 나만 안된다고 혼자서 이리도 고생을 하는건지....
정말 미치도록 알고 싶었습니다.

그래서 결국....파이썬의 소스를 보기로 했습니다.

마이크로 소프트가 언급한 DLL의 탐색 경로에 들어가 있음에도 자꾸 DLL을 찾지 못한다고 나오는게 너무 답답해서 누가 잘못하고 있는건지 알아봐야겠습니다.

이젠 귀찮아서 사진도 어지간하면 안올릴 생각이다.

다운로드 받은 소스는 2.7.11
https://www.python.org/downloads/release/python-2711/


소스 분석엔 소스인사이트가 최고.

핵심만 빠르게 찾아가기 위해서 메시지를 바로 찾아 보는게 장땡.

"DLL load failed"라는 문자열로 검색한 결과

dynload_os2.c
dynload_win.c

위의 두개 파일만 검색 된다...그나마 다행.
이름을 보니 볼 거 없이 dynload_win.c가 내가 찾는 파일임이 확실하다.

dynload_win.c

DLL load failed는 저기 보이는 소스에서 조금 더 내려가면 나온다.

저기서 봐야 할 것은 GetFullPathName()과 LoadLibraryEx().

먼저 해당 함수에 대한 MSDN의 설명을 참조.

GetFullPathName()

첫번째 두번째 인자가 입력이고 세번째 네번째가 출력.
그러니까 pathname을 넣고 pathbuf를 받아온 것이다.

그러면 다음엔 pathname이 아닌 pathbuf를 사용해야 할텐데, 다음의 LoadLibraryEx()에서는 pathname을 사용하고 있다.???

LoadLibraryEx()에 대한 설명도 찾아 보자.


LoadLibraryEx()

이 함수는 좀 복잡한데 마지막 인자인 dwFlags에 따라서 DLL 탐색의 순서나 방법이 달라진다고 한다.

LoadLibraryEx()의 dwFlags 설명 중.

이 플래그에 대한 설명도 참 복잡한데, LOAD_WITH_ALTERED_SEARCH_PATH를 사용할 때에는 반드시 파일을 절대 경로로 적어야 한다는 것.
그리고 탐색방법은 아래에 설명....한다고 되어 있는데, 설명이 없다.휴....

다른 페이지에서 설명을 찾았는데,

Dynamic-Link Library Search Order이라는 페이지이고,

여기에서
Alternate Search Order for Desktop Applications
이라는 항목을 찾아보면 설명이 나와 있다.
하지만 해당 항목을 읽어보면 알겠지만 통상적으로 탐색을하는 디렉토리의 순서가 다를 뿐 크게 문제가 되지는 않아보인다.

그렇다면 문제가 될 것으로 예상되는 건, 앞서 LoadLibraryEx()에서 LOAD_WITH_ALTERED_SEARCH_PATH 플래그 사용시 반드시 절대경로를 사용해야 한다는 문구였다. 절대 경로가 아닐 경우에는 결과가 어찌될지 모른다는게 설명...


과연 파이썬 소스에 결정적인 문제가 있어서 이것이 원인이었는지를 확인하려면,

1. 직접 파이썬을 빌드하고 해당 부분을 적절하게 수정한 뒤 문제가 해결되는지 확인한다.

2. 파이썬 3.x의 경우에는 이 부분이 같은지 다른지 확인하고, 또 문제가 발생하는지 여부를 확인해 본다.
  2-1. 파이썬 3.x도 소스가 같고 문제도 동일하게 발생한다면 위의 1번 방법으로 확인해야 한다.
  2-2. 파이썬 3.x도 소스가 같은데 문제가 발생하지 않는다면, 문제의 원인은 다른 곳에 있다는 의미이다. 골치 아픈 케이스.
  2-3. 파이썬 3.x는 소스가 다르고 문제가 발생하지 않는다면 3.x의 소스를 최대한 활용해서 무엇이 문제였는지 최대한 유추해 볼 수 있다. 하지만 결국엔 1번의 과정을 밟아야 한다.
  2-4. 파이썬 3.x는 소스가 다른데 문제가 동일하게 발생한다면 완전히 별개의 문제로서 따로 따로 소스를 분석해야 하지만, 파이썬 소스의 문제가 아니라 내가 사용하는 환경의 문제일 가능성이 높아진다.

3. 최소한의 비용으로 최대한의 결과를 얻기위해 리버싱으로 살짝만 확인해본다.(?)


이상의 계획을 가지고 생각해보니, 먼저 2번의 과정을 거치는게 빠르겠다 싶었다.

그래서 파이썬 3.x의 소스를 받아서 확인해 본 결과....소스가 달랐다.

아예 LoadLibraryEx()를 부르는 함수에 들어오기 전에 먼저 처리를 한게 아닐까 싶게...그래서 소스만으로 비교를 하기엔 무리가 있어서 직접 실행해 보기로 했다.

그.런.데......파이썬 3.x는 Windows Vista이상에서만 돌아간단다.....설치도 안된다...ㅠ.ㅠ

결국 2번의 방법은 몽땅 수포로 돌아가고....

1번의 정공법이냐, 3번의 편법이냐....만 남은 상황이다.

2014년 11월 5일 수요일

Vim 파일 저장 오류 __ 10

최종 오류의 원인으로 등장한 stat() 함수.
하지만 DOSBox에서는 실패한 이 함수의 결과가 시험용을 작성한 코드에서는 성공했다.
어째서 다른 결과가 나온 걸까?

gdb를 이용해서 어셈블리 코드 레벨의 실행 절차마저 세세하게 따져봐야 할 지경에 이르게 되었다.
하지만 Linux gdb에서의 어셈블리 코드의 표기가 MS-Windows 계열에서 사용하는 표기와 너무 달라서 해독이 난감해 하던 터였다.

일단, 지난 번에 만든 stat() 함수를 사용하는 테스트용 C program의 Assembly code를 생성해 보았다.
실행 결과야 이미 알고 있으니 최대한 단순하게 만들어서 Assembly code도 간단하도록 간략화 시켰다.

stat() 테스트 프로그램

gcc에서 -S 옵션을 사용하면 Assembly Code를 출력한다.
gcc -S 옵션
그렇게 만들어진 Assembly Code는...
테스트 프로그램의 Assembly Code
역시나 뭔가 참 어색하다.
상수값에 $를 쓴다거나 레지스터 이름에 %를 붙인다는 걸 알 수 있지만, 오퍼랜드의 순서가 바뀌어 있고, %gs:20 ?? 156(%esp) ??? 이건 대체 뭘까?

Linux용 Assembly 공부를 해야 하나 하고 관련 서적과 자료들을 인터넷에서 검색을 했다.

헌데... CPU는 동일한 인텔 계열인데 굳이 Assembly 공부를 다시 해야 하나?
OS에 관련된 부분을 제외하면 단순히 표기법만 다른 것 아닌가?

그렇다면 gcc에서 Assembly Code를 출력할 때 이 표기법을 바꿀 수 있지 않을까?
전에 어디에선가 본 기억으로는 Assembly Code의 표기법은 AT&T와 Intel의 방식으로 나뉘어져 있으며, AT&T 표기법은 Unix 계열에서, Intel 표기법은 MS-Windows 계열에서 주로 사용한다고 했던 것 같다.
gcc는 MS-Windows용으로도 porting되어 있으니 양쪽 표기법을 모두 지원할 것이라 생각이 들어 gcc 매뉴얼을 다시 살펴 보았다.

그래서 찾아낸 옵션, -masm=intel로 지정해주면 된다.
-masm 옵션
그렇게 만들어진 Assembly Code,
테스트 프로그램의 Assembly Code. Intel 표기법
이제야 조금 익숙해진 모양새.

그렇다면 gdb에서도 Assembly Code룰 보여줄 때 표기법을 바꿀 수 있지 않을까?
그래서 gdb 매뉴얼을 찾아 본 결과,
gdb의 disassemble 옵션

2014년 10월 30일 목요일

버그와 디버깅에 관한 단상

디버깅에 집중하다 보니,
마지막 포스팅에서의 쓸데없는 생각, 자기 자신을 (온전히) 디버깅할 수 있는 프로그램은 없다...

오늘 밤, 아니군 어제 밤, 간만에 산책을 하면서 들어 온 생각
자기 자신을 디버깅 할 수 있는 머신은 과연 불가능한 걸까?
(현재의 프로그램이라는 좁은 제한을 벗어나 모듈화 되고 병렬처리가 가능하고 자기 복제도 가능한 등의 H/W와 S/W를 모두 갖춘 진보된 장치라면 가능하지 않을까?
그리고 이런 기술적인 문제를 넘어서의 고차원적인 문제를 생각해 본 것이다.)

극장판 애니메이션 [공각기동대]의 초반부에 이런 대사가 나온다.
버그가 없는 프로그램도 없지만, 디버깅이 불가능한 프로그램도 없지.




그런가?

2001: A Space Odyssey에는 HAL 9000이라는 인공지능 컴퓨터가 등장한다.
탁월한 능력을 지녔으며 우주선의 모든 것을 관리/제어하는 중요한 역할을 한다.
하지만 지구와의 통신을 위한 위성 안테나 모듈에 문제가 있다는 잘못된(?) 판단을 내린다.
우주선의 항해사들은 HAL 9000에 버그가 발생했다고 생각을 하지만 HAL 9000은 그렇지 않다고 생각한다.

버그를 제거하는 디버깅의 시작은 버그를 인식하는 것이다.
HAL 9000이 제아무리 뛰어나다 해도 그것이 버그라고 인식하지 못한다면 디버깅은 불가능하다.

그렇다면 과연 그것이 버그였을까?
엄격하게 따지자면 그건 버그가 아니었다.
그 문제를 보는 이의 시각에 따라 옳고 그름이 갈리기 때문이다.
그리고 HAL 9000은 나름대로의 이유가 있었기에 안테나 모듈의 문제를 제기했던 것이다.
하지만 항해사들의 입장에서는 문제 없는 모듈에 문제가 있다고 교체를 강요하는 HAL 9000에 큰 버그가 있다고 생각했던 것이다.

만약 모든 입장, 모든 치우침, 모든 편견에서 자유로워진다면 버그라고 인식할 것이 없는 건 아닐까?
결국은 극히 제한된 일부로써의 편향된 입장을 가지게 되면 버그로 인식할 것은 매우 많아지는 것이고, 버그는 그 자체가 문제가 아니라, 그걸 바라보는 이의 편향된 생각이 만들어낸 왜곡된 환상이었던 건 아닐까?


일본의 만화가 우라사와 나오키의 [플루토]를 보면 이런 이야기가 나온다.
최고의 로봇을 만들기 위해 고민을 하던 텐마 박사는 결국 모든 인류의 특성을 한데 모아서 자신의 로봇에게 주입을 했고, 기동을 시켰으나 결국 그 로봇은 깨어나지 못했다고 한다. 모든 인류의 특성을 가진 롯봇은 결국 자신의 주체를 혼동하여 결정하지 못했기 때문이라고...




2014년 10월 25일 토요일

Vim 파일 저장 오류 __ 8

디버그 메시지를 확인하던 중, 메시지의 출력이 되지 않아 확인을 하지 못하고 중단이 되었었다.
SetFileAttr()
하지만 추가적으로 확인해 본 결과, 메시지의 출력은 정상적으로 되었다.
단지, 내가 추가한 부분에 걸리지 않았던 것 뿐.
DOS_SetFileAttr()이 호출되면 중간에는 아무런 문제가 없이 마지막의 GetFileAttr()까지 오는 것이었다.

하지만 소스에서 보듯이 GetFileAttr()은 함수포인터로 호출되므로 정확한 파일 이름을 알 수가 없다.
GetFileAttr() 검색
가상함수인 GetFileAttr()은 드라이브의 종류에 따라 각기 달리 구현되어 있다.
확인해 본 결과 이번 경우에는 drive_local.cpp에 있는 함수가 호출되는 것을 알게 되었다.

그래서 GetFileAttr()에 메시지 추가.
문제가 발생하는 부분은 stat()함수가 실패했기 때문이었다.
GetFileAttr()

stat() 도움말

stat() 도움말 (계속)

stat() 도움말 (계속)

다시 빌드하고 디버그 메시지 확인...

메시지를 봐도 특별히 이상한 점은 찾을 수가 없다.

위의 stat()에 대한 도움말을 읽어 보니, 실패했을 경우에는 errno에 에러 코드를 설정한다고 한다.
그래서 메시지에 errno의 값을 함께 출력하도록 수정.
GetFileAttr()에 메시지 추가

디버그 메시지로 출력된 errno의 값은 2.
debug 출력

errno = 2는 "No such file or directory"...
파일이 없다니....
errno 값의 의미

완전히 막혀버린 상황.
stat() 함수는 기본적인 C 함수이기 때문에, 더 이상의 디버깅을 해도 소용이 없게 된다.
이 문제는 vim의 문제도 아니고 DOSBox의 문제도 아닌 Ubuntu의 문제가 되기 때문이다.

지금으로썬 Ubuntu(혹은 Linux)에서의 DOSBox는 문제가 있다는 것으로 결론을 내릴 수 밖에 없다.

2014년 10월 24일 금요일

Vim 파일 저장 오류 __ 7

예전에 만들어 두었던 debug 버전의 DOSBox를 실행해 보았다.


디버그 터미널에는 여러가지 정보가 표시된다.
DOSBox 화면에서 Alt-Pause를 누르면 디버그 모드를 진입하게 된다.

지금은 디버그 모드로 진입하지 않고 단지 디버그 터미널에 출력되는 내용만 확인해 보았다.

먼저, 기존에 존재하던 "NEWFILE"이라는 파일을 vim으로 열었을 때 디버그 터미널에는 다음과 같은 내용이 출력된다.
"vim NEWFILE"을 실행

파일을 수정하고 ":w"를 입력하여 저장을 시도했다.
역시나 저장되지 않았고, 디버그 터미널에는 다음과 같은 내용이 출력되었다.
수정 후 저장 시도
[Set File Attribute]는 not supported라는 메시지를 출력한다.
아무래도 이 부분이 의심스럽다.

그렇다면 vim이 아닌 다른 에디터는 대체 어째서 문제가 없다는 것일까?
edit를 이용해서 같은 파일을 열어 보았다.
"edit NEWFILE"을 실행

수정을 하고 저장을 해 보았다.
수정 후 저장
Attribute 따위는 아무것도 없다.
file open command의 파라미터가 0인지 1인지에 따라 load/save를 수행하는 듯 하다.
그냥 저장만 하고 끝.

DOSBox의 디버그 메시지에 대해서 자세히 확인하기 위해서는 DOSBox의 소스에서 해당 메시지를 찾아 봐야 하겠다.

DOSBox 소스 검색
"file open command"는 dos_files.cpp의 DOS_OpenFile()에서 출력하는 메시지로, 다음에 오는 숫자는 다음과 같은 의미를 가지고 있다.
0 : read
1 : write
2 : read & write

"file create attributes"는 dos_files.cpp의 DOS_CreateFile()에서 출력하는 메시지로, 다음에 오는 숫자가 attribute를 나타낸다.

"Set File Attributes"는 dos.cpp의 DOS_21Handler()에서 출력하는 메시지이다.
MS-DOS Interrupt Handler를 에뮬레이션 하는 부분인데, 해당 메시지가 출력되는 Interrupt는
AH = 0x43, AL = 0x01, Set File Attribute라고 명시되어 있는 부분이다.

MS-DOS Interrupt, Set File Attributes

그런데 해당 소스를 보면 좀 이상하다.
Interrup Handler가 구현이 안 된것도 아닌데, 아래쪽의 처리를 하기도 전에 "not supported"라는 메시지를 출력하고 있다는 것이다.

일단, MS-DOS Interrupt 21h, ah = 0x43, al = 0x01에 대한 설명을 찾아보면,
디음과 같은 상세한 설명을 볼 수 있다.
MS-DOS Interrupt 21h, ah=0x43, al=0x01

DOS_SetFileAttr()의 소스는 다음과 같다.
소스를 보니, 주석에 설명한 바와 같이 실제로는 파일의 속성을 바꾸지는 않고 파일의 속성을 읽어 올 뿐이었다.
DOS_SetFIleAttr()

그러면 과연 어떤 부분에서 문제가 되어서 에러가 발생하는 것인지 확인하기 위해, 디버그 메시지를 추가해 보기로 했다.
dos.cpp에 메시지 추가

dos_files.cpp, DOS_SetFileAttr()에 메시지 추가

이제 DOSBox를 다시 빌드해야 하는데, 예전에 어떤 설정으로 빌드했는지 모르니 처음부터 다시해야 한다.
디버그 모드로 빌드하기 위해 "./configure --enable_debug=heavy"
DOSBox 빌드, configure

그리고 make
DOSBox, make

이제 DOSBox를 실행하고 아까와 동일하게 "vim NEWFILE" 실행한 경우의 디버그 메시지들을 확인해 보자.
"vim NEWFILE"의 디버그 메시지

그리고 저장했을 때의 디버그 메시지는...
":w"로 저장했을 때의 디버그 메시지
지정한 파일의 속성은 archive(0x20)이고, 에러 코드(2)의 의미는 "file not found"라고 한다.

그런데, 더 구체적인 오류 메시지인 DOS_SetFileAttr()의 메시지는 전혀 출력이 안되었다.
무슨....?
로그 메시지 출력에 어떤 제한이 있는지 다시 확인해 봐야 하겠다.
어차피 실제 속성을 바꾸지 않는 함수인만큼, 오류의 원인을 확인해 보고 별 문제가 아니라면 그냥 성공한 것으로 리턴하게 만들어야 하지 않을까?

나머지는 다음에...

2014년 10월 21일 화요일

Vim 파일 저장 오류 __ 5

Borland C++의 매뉴얼은 워낙에 구석기 유물인지 찾기가 곤란...
그래서 BC++ IDE의 Help를 활용하기로 했다.

Borland C++ IDE help

_chmod()의 도움말 화면
_chmod의 help

두번째 인자 func가 0이면 get, 1이면 set 기능을 하게 된다.
_chmod의 help (계속)

세번째 인자인 DOS file-attribute는 다음과 같다.
file attribute
실제 값을 확인하기 위해서 DOS.H를 확인해 보았다.
DOS.H
여기서 지난번에 추가한 디버그 메시지를 다시 확인해 보자.
추가했던 디버그 메시지
위의 메시지에서 p=32(0x20)은 mch_open()에서 세번째 인자로 사용될 perm이라는 변수에 할당된 값이며, _chmod() 함수를 이용해 얻은 값이다.
즉, 변수의 이름은 UNIX 파일 시스템의 권한(permission)을 의미하는 듯이 보이지만, MS-DOS 파일 시스템에서는 권한이라는 것이 없기에 파일의 속성만을 나타내고 있는 것이다.

다시 한번 에러가 발생한 부분의 code를 살펴보자.
FILEIO.C
위의 mch_open()이 실패한 것이 문제였고, mch_open()의 세번째 인자로 perm 변수를 사용하고 있음을 볼 수 있다.
하지만 이 소스만 보아도 문제의 소지가 있음을 알 수 있는 것이, 0666, 0777은 UNIX 파일 시스템에서만 유효한 권한(permission)이기 때문이다.
DOS의 파일 속성(읽기,쓰기,숨김,시스템,디렉토리)과 UNIX의 권한(소유자,그룹,관리자의 읽기,쓰기,실행 권리)를 서로 같은 것으로 간주해서 다루고 있다는 것이다.

그러면 정말로 이렇게 온동하여 처리한 것이 문제가 되는 것일까?
앞서 디버그 메시지에서는 perm이 0x20이었음을 확인했다.
8진수인 0777은 0x1FF, AND 연산을 한다해도 여전히 0x20이 되므로 결과적으로는 문제가 되지 않을 것으로 보인다.
그러면 뭘까?

mch_open()을 다시 확인해 보자.
mch_open()은 open()로 연결되어 있다.
mch_open() 매크로
open()의 help를 확인해 보자.
open()의 help
세번째 인자인 mode는 생략이 가능한 것으로 나와있다.
open()의 help (계속)
mode를 더 확인해 보니,
mode의 help
_chmod()의 file-attribute와는 다른 상수들이다.
실제 값은 어떨까?
sys/stat.h의 mode
이렇게 보니 _chmod()와 open()은 전혀 다른 계통의 함수들로 연계하여 사용하기에는 문제가 있어보인다.
open()은 기존의 UNIX 파일 시스템과의 호환성을 염두에 두고 MS-DOS에 포팅이 되었다고 한다면 _chmod()는 MS-DOS의 파일시스템에서만 사용할 수 있게 독자적으로 만들어진 것으로 보인다.


그렇다면, mch_open()의 세번째 인자의 값을 바꾸어주면 문제가 없을까?
하지만 정말 이 부분이 문제였다면, Windows에서 DOSBox를 구동하여 vim을 사용했을 때에도 동일한 문제가 발생해야 한다.
암튼 일단은 세번째 인자를 고쳐서 해 보기로 하자.

vim의 소스들을 살펴보니 대부분 세번째 인자로 0을 사용하고 있으며, 위의 stat.h에서도 일반적인 파일은 0을 사용한다고 되어 있기에 무조건 0을 사용하도록 수정해 보았다.
FILEIO.C
DOSBox에서 다시 make
make
그리고 기존의 파일을 열어서 수정하고 다시 저장해보니...
save
역시 예상과 같이 이것이 문제가 아니였던듯....