윈도우 파이썬 기본버전 설정
How Should I Set Default Python Version In Windows?
    https://stackoverflow.com/a/5088548

환경변수 PY_PYTHON 설정하면 된다.

set PY_PYTHON=2
set PY_PYTHON=3

set PY_PYTHON=2.7
set PY_PYTHON=3.8


C:\>assoc .py
.py=Python.File

C:\>ftype Python.File
Python.File="C:\Windows\py.exe" "%1" %*

C:\>ftype Python.NoConFile
Python.File="C:\Windows\pyw.exe" "%1" %*

C:\>py -0
Installed Pythons found by py Launcher for Windows
 -3.8-64
 -3.8-32
 -3.7-64
 -3.5-64
 -3.4-64
 -2.7-64 *
by 시험さま | 2021/11/02 16:55 | 컴퓨터 | 트랙백 | 덧글(0)
Using a 32-bit COM Object from a 64-bit Application
이걸로 결국 문제가 해결되지는 않았지만,
api = win32com.client.DispatchWithEvents("SomeCOM.API", APIEvents)
호출시의 아래와 같은 오류가 사라지는 정도의 변화는 있었다.

Traceback (most recent call last):
  File "C:\Python38\lib\site-packages\win32com\client\dynamic.py", line 86, in _GetGoodDispatch
    IDispatch = pythoncom.connect(IDispatch)
pywintypes.com_error: (-2147221021, '작업을 사용할 수 없습니다.', None, None)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\test\main.py", line 52, in <module>
    api = win32com.client.DispatchWithEvents("SomeCOM.API", APIEvents)
  File "C:\Python38\lib\site-packages\win32com\client\__init__.py", line 312, in DispatchWithEvents
    disp = Dispatch(clsid)
  File "C:\Python38\lib\site-packages\win32com\client\__init__.py", line 117, in Dispatch
    dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch, userName, clsctx)
  File "C:\Python38\lib\site-packages\win32com\client\dynamic.py", line 106, in _GetGoodDispatchAndUserName
    return (_GetGoodDispatch(IDispatch, clsctx), userName)
  File "C:\Python38\lib\site-packages\win32com\client\dynamic.py", line 88, in _GetGoodDispatch
    IDispatch = pythoncom.CoCreateInstance(
pywintypes.com_error: (-2147221164, '클래스가 등록되지 않았습니다.', None, None)


링크정도는 남겨두는게 좋겠다.

Using a 32-bit COM Object from a 64-bit Application
    https://www.codeproject.com/Tips/267554/Using-32-bit-COM-Object-from-64-bit-Application
by 시험さま | 2021/11/02 14:01 | 컴퓨터 | 트랙백 | 덧글(0)
gcc -pie vs. -no-pie
디스어셈블 주소지 질문
  https://kldp.org/node/164466

https://stackoverflow.com/questions/37864773/computing-offset-of-a-function-in-memory
--> https://stackoverflow.com/a/37932094


ELF 베이스 주소?

# 링크스크립트가 모여있는 디렉토리.
# 대충 아래와 같이 검색해보면 베이스주소들이 보임.
for f in /usr/lib/x86_64-linux-gnu/ldscripts/*; do echo $f; grep -E "__executable_start|__image_base|Script for" $f; done | less
for f in /usr/lib/x86_64-linux-gnu/ldscripts/*86*; do echo $f; grep -E "__executable_start|__image_base|Script for" $f; done | less
for f in /usr/lib/x86_64-linux-gnu/ldscripts/*x86*; do echo $f; grep -E "__executable_start|__image_base|Script for" $f; done | less

-no-pie 바이너리의 경우,
  -- elf_i386* 스크립트들이 만드는 elf32-i386 바이너리는 0x8048000 베이스주소와 함께 만들어진다 (gcc -m32).
     (관련의견 : https://www.spinics.net/lists/linux-assembly/msg00245.html)
  -- elf_x86_64* 스크립트들이 만드는 elf64-x86-64 바이너리는 0x400000 베이스주소와 함께 만들어진다 (gcc -m64).
  -- elf32_x86_64* 스크립트들이 만드는 elf32-x86-64 바이너리도 0x400000 베이스주소와 함께 만들어진다 (gcc -mx32).

- centos-7까지는 -no-pie가 기본상태였음. centos-8은 테스트시스템이 없어 확인해보지 못함.
- ubuntu-16.04 까지는 -no-pie가 기본, 18.04부터는 -pie가 기본이었음.

Base Address of ELF
  https://stackoverflow.com/questions/18296276/base-address-of-elf

chanik@dev-ubuntu:~/test/elf_base$ ld -melf_i386 --verbose | grep __executable_start
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS;
chanik@dev-ubuntu:~/test/elf_base$ ld -melf_x86_64 --verbose | grep __executable_start
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
chanik@dev-ubuntu:~/test/elf_base$ ld -melf32_x86_64 --verbose | grep __executable_start
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
chanik@dev-ubuntu:~/test/elf_base$ ld -melf_i386 -pie --verbose | grep __executable_start
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0)); . = SEGMENT_START("text-segment", 0) + SIZEOF_HEADERS;
chanik@dev-ubuntu:~/test/elf_base$ ld -melf_x86_64 -pie --verbose | grep __executable_start
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0)); . = SEGMENT_START("text-segment", 0) + SIZEOF_HEADERS;
chanik@dev-ubuntu:~/test/elf_base$ ld -melf32_x86_64 -pie --verbose | grep __executable_start
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0)); . = SEGMENT_START("text-segment", 0) + SIZEOF_HEADERS;


훌륭한 자료 : What is the -fPIE option for position-independent executables in gcc and ld?
  https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-position-independent-executables-in-gcc-and-ld

훌륭한 자료 : difference between i386:x64-32 vs i386 vs i386:x86_64
  https://stackoverflow.com/questions/36347063/difference-between-i386x64-32-vs-i386-vs-i386x86-64

 architecture :  emulation   :   format     :       triple
-------------   ------------   ------------   -------------------
- i386:x64-32 : elf32_x86_64 : elf32-x86-64 : x86_64-linux-gnux32 : (64-bit 시스템에서만 동작하는 새로운 32-bit 바이너리. x86_64 새 레지스터 등 다 가용)
- i386        : elf_i386     : elf32-i386   : i[3-6]86-linux-gnu  : (전통적인 32-bit 바이너리. x86_64의 새 레지스터 등 사용 불가능)
- i386:x86_64 : elf_x86_64   : elf64-x86-64 (64-bit 바이너리)     : x86_64-linux-gnu


objdump -f /lib/ld-linux.so.2 /lib64/ld-linux-x86-64.so.2 /libx32/ld-linux-x32.so.2
objdump -f /lib*/ld*.so*

chanik@dev-ubuntu:~/test/elf_base$ cat t.c
int main(void) { return 0; }
chanik@dev-ubuntu:~/test/elf_base$ gcc -o t1 t.c -no-pie
chanik@dev-ubuntu:~/test/elf_base$ gcc -o t2 t.c -pie
chanik@dev-ubuntu:~/test/elf_base$ gcc -o t3 t.c -static-pie
chanik@dev-ubuntu:~/test/elf_base$ objdump -t t1 | grep ' main'
0000000000401106 g     F .text  000000000000000f              main
chanik@dev-ubuntu:~/test/elf_base$ objdump -t t2 | grep ' main'
0000000000001129 g     F .text  000000000000000f              main
chanik@dev-ubuntu:~/test/elf_base$ objdump -t t3 | grep ' main'
00000000000cb6c0 l     O .data  0000000000000898 main_arena
000000000000a019 g     F .text  0000000000000027 main
chanik@dev-ubuntu:~/test/elf_base$ ./t1
0x401136
chanik@dev-ubuntu:~/test/elf_base$ ./t1
0x401136
chanik@dev-ubuntu:~/test/elf_base$ ./t2
0x55625babb149
chanik@dev-ubuntu:~/test/elf_base$ ./t2
0x5564cc7c6149
chanik@dev-ubuntu:~/test/elf_base$ ./t2
0x562b8a1e8149
chanik@dev-ubuntu:~/test/elf_base$ ./t3
0x7f0d34de9019
chanik@dev-ubuntu:~/test/elf_base$ ./t3
0x7f1699391019
chanik@dev-ubuntu:~/test/elf_base$ ./t3
0x7f035a5d7019
chanik@dev-ubuntu:~/test/elf_base$ ls -al
total 944
drwxrwxr-x 1 chanik chanik     38 Apr 16 11:07 .
drwxrwxr-x 1 chanik chanik    674 Apr 15 13:13 ..
-rw-rw-r-- 1 chanik chanik   3317 Apr 16 11:07 readme.txt
-rwxrwxr-x 1 chanik chanik  16624 Apr 15 10:20 t1
-rwxrwxr-x 1 chanik chanik  16696 Apr 15 10:20 t2
-rwxrwxr-x 1 chanik chanik 917256 Apr 16 10:18 t3
-rw-rw-r-- 1 chanik chanik     70 Apr 15 10:19 t.c
by 시험さま | 2021/04/16 11:04 | 컴퓨터 | 트랙백 | 덧글(0)
DLL virtual address
DLL을 만드는 이유중 하나는,
동일 DLL이 차지하는 메모리 공간을 서로 다른 프로세스들이 공유할 수 있기 때문이다.
각 프로세스들이 나름대로의 가상주소 위치로 DLL 코드를 매핑하겠지만
그 가상주소들은 동일한 실 메모리 페이지들을 가리킨다..??

이렇게 생각하고 있었는데, 실상은 좀 다른 모양이다.

Windows DLL은 PE 헤더에 (링크할때 설정 가능한) prefered base address를 담고 있는데,
이 가상메모리 주소로 로드되는 경우에만 다른 프로세스와 메모리 페이지가 공유 가능한 듯 하다.
DLL 로드할때 해당 베이스주소가 이미 다른 DLL 등에 의해 사용중이면
어쩔 수 없이 다른 가상주소 위치로 읽어들이는 재배치(relocation)가 일어나게 되고
이 경우 점프명령어 주소수정이 일어나는 코드페이지들은 CoW(Copy on Write) 프로텍션에 의해
새 물리페이지로 복사이전 되므로 해당 코드페이지들은 더이상 타 프로세스와 공유되지 않음.

(Windows에서 이렇다는 것이고, 아마 Linux에서는 .so(Shared Object)를 만들때 PIC로 만들어지므로
 프로세스마다 서로 다른 가상주소로 매핑된 .so 코드 페이지들도 서로 공유되는 모양이다.
참고: https://en.wikipedia.org/wiki/Position-independent_code
position-independent code (PIC) or position-independent executable (PIE) is a body of machine code that, being placed somewhere in the primary memory, executes properly regardless of its absolute address. PIC is commonly used for shared libraries, so that the same library code can be loaded in a location in each program address space where it does not overlap with other memory in use (for example, other shared libraries))

따라서 DLL을 링크할때 다른 DLL들과 충돌하지 않도록 적절히 베이스주소를 설정해줘야 메모리 공유가 이뤄지겠는데
문제는, 아무 생각없이 사용자 DLL을 만들어 링크하면 베이스 주소가 기본값(0x10000000)으로 설정되므로
사용자 DLL이 여러개 로드될 경우 재배치가 일어날 수밖에 없다는 것.


Modify the Base Addresses for a DLL Files Series
    https://www.codeproject.com/Articles/35829/Modify-the-Base-Addresses-for-a-DLL-Files-Series

A Dynamic-link library created in Microsoft Visual C++ has default base address 0x10000000 (Visual C# has default base address 0x400000). That means, when the process starts, the system loader tries to load the DLL to this address in the process memory. However, if a number of DLLs have the same base address, only one of them is loaded to its default address. For all other DLLs, the loader makes the relocation: changes the memory addresses in DLL commands according to the new base address where the DLL is loaded. This process is also known as DLL collisions.


Loading Applications and DLLs
    https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection

DLLs are created with a default base address. Every process that uses a DLL will try to load the DLL within its own address space at the default virtual address for the DLL. If multiple applications can load a DLL at its default virtual address, they can share the same physical pages for the DLL. If for some reason a process cannot load the DLL at the default address, it loads the DLL elsewhere.


If relocated DLLs cannot share pages, then doesn’t ASLR cause all pages to be non-shared?
    https://devblogs.microsoft.com/oldnewthing/20160413-00/?p=93301

구식 DLL들은 재배치(relocate)될 경우 프로세스간 메모리 공간 공유가 이뤄지지 않는다.
그럼 ASLR 켜진 상태로 링크된 DLL들은 로드할 때 적재주소가 랜덤화되므로 공유가 불가능한가 하면, 그렇지 않다.
DLL을 최초 로드할 때 랜덤화된 상태가 이후 다른 프로세스에서 DLL을 로드할 때 재활용되면서
메모리페이지가 공유되는 모양이다.

The solution is that when a DLL is loaded, ASLR chooses a random destination address, but it then remembers that address for future use, and if another process loads the DLL, the kernel will try to use the same destination address for the DLL in that other process. This means that if two processes load a DLL, that DLL will probably get the same destination address in both processes, which establishes one of the prerequisites for sharing.


Six Facts about Address Space Layout Randomization on Windows
    https://www.fireeye.com/blog/threat-research/2020/03/six-facts-about-address-space-layout-randomization-on-windows.html

by 시험さま | 2021/03/08 12:30 | 컴퓨터 | 트랙백 | 덧글(0)
ASUS TUF Gaming B460M-PLUS STCOM
ASUS TUF Gaming B460M-PLUS STCOM
    http://www.nowpug.com/field/460601

전력제한만 해제하고 싶을 때,

Ai Tweaker -> Internal CPU Power Management
  - CPU Core/Cache Current Limit Max.: 255.75
  - Long Duration Package Power Duration : 4095
  - Short Duration Package Power Duration : 4095

이 상태로 쓰면 CPU를 All Core Boost 클럭으로 쓸 수 있을 것이다.
Windows 10에서 전원설정을 "고성능"으로 설정해두면
아마 클럭이 계속 부스트 상태로 머무를 것이다.

MSI 박격포 시리즈는 전력제한이 해제된 상태로 출시되므로
이런 설정 하지 않아도 되는 모양이다. 추측임.
by 시험さま | 2021/01/20 17:42 | 컴퓨터 | 트랙백 | 덧글(0)
RHEL7/CentOS 7 – Recover/Reinstall GRUB2 with UEFI
P8Z68-V Pro/Gen3 보드에 x86_64-efi 상태로 CentOS7이 설치돼있는데
윈도우10 설치된 SSD를 달아 윈도우10으로 부팅했다가
다시 CentOS7 설치된 SSD로 교체했더니 부팅 불가능 상태로 빠졌다.

아예 grub도 못찾는 채로, 부팅 가능한 디스크를 넣으라는 식으로 나왔다.

일단 grub 재설치를 시도했다.
CentOS7 설치DVD로 복구모드 부팅하여 아래와 같이 시도했다.
( DVD부팅 -> Troubleshooting -> Rescue a CentOS Linux system -> 1) Continue -> press <return> to get a shell -> chroot /mnt/sysimage -> 인터넷 접근 필요시 ifconfig 또는 dhclient 로 IP 설정 )

# grub2-install /dev/sda
grub2-install: error: /usr/lib/grub/x86_64-efi/modinfo.sh doesn't exist. Please specify --target or --directory.

위와 같이 grub 재설치 오류가 발생했고,
아래와 같이 패키지 추가설치후 grub2-install 정상 동작함

# yum install grub2-efi-x64-modules
# grub2-install /dev/sda

여기까지 하고 부팅해보니 grub> 프롬프트까지는 떴다.
하지만 그 이상은 진행되지 않음.
다시 설치DVD로 부팅하여,

# cd /boot/efi/EFI/centos/
# ls -al
total 7036
drwx------. 4 root root    4096 May 12 14:14 .
drwx------. 4 root root    4096 Apr 23  2020 ..
-rwx------. 1 root root     134 Feb 22  2019 BOOT.CSV
-rwx------. 1 root root     134 Feb 22  2019 BOOTX64.CSV
drwx------. 2 root root    4096 Apr 23  2020 fonts
drwx------. 2 root root    4096 Nov  9  2018 fw
-rwx------. 1 root root   68168 Nov  9  2018 fwupia32.efi
-rwx------. 1 root root   77600 Nov  9  2018 fwupx64.efi
-rwx------. 1 root root    5455 Sep 10 08:10 grub.cfg
-rwx------. 1 root root    1024 Apr 23  2020 grubenv
-rwx------. 1 root root 1090976 Aug  8  2019 grubx64.efi
-rwx------. 1 root root 1151864 Feb 22  2019 mmx64.efi
-rwx------. 1 root root 1151864 Feb 22  2019 MokManager.efi
-rwx------. 1 root root 1205248 Feb 22  2019 shim.efi
-rwx------. 1 root root 1198984 Feb 22  2019 shimx64-centos.efi
-rwx------. 1 root root 1205248 Feb 22  2019 shimx64.efi

정상동작하는 PC에서는 grubx64.efi 파일이 위와 같이 10MB 정도로 존재하는데
문제가 생긴 PC에서는 훨씬 작은 크기(1/10 정도 크기)로 만들어져 있었다.

정상동작하는 PC로부터 복사해 넣어봤지만,
grub2-install 명령을 실행할 때마다 작은 크기로 새로 만들어지고 있었음.

구글 검색하며 이짓 저짓 해보다가,
아래의 안내자료를 따라 grub2-install 실행후 아래 명령을 실행해보니 정상 크기로 다시 만들어졌다.
이 상태로 재부팅해보니 부팅 성공.

RHEL7/CentOS 7 – Recover/Reinstall GRUB2 with UEFI
    https://www.unixarena.com/2018/05/rhel7-centos-7-recover-reinstall-grub2-with-uefi.html/

# yum reinstall grub2-efi shim

grub2-efi-x64-modules 패키지는 grub2-install 실행을 위해 새로 설치으나 이젠 불필요한 것 같아 제거함.

# yum remove grub2-efi-x64-modules

# exit
# init 6


------

처음 겪었을땐 CentOS7 설치된 SSD의 grub이 깨진 것이라 여겼는데,
두 번째 겪어보니 CentOS7 SSD에 아무 변경사항이 없어도 발생하는 문제였다.
상황을 정리해보면 아래와 같았다.

1. CentOS7 SSD만 달린 상태에서 CentOS7 사용하다가 종료후 CentOS7 SSD 제거,
2. 이후 윈도우10 SSD만 달고 윈도우10 부팅하여 사용하다가 종료후 윈도우10 SSD 제거,
3. 다시 CentOS7 SSD 달고 부팅시도했으나 부팅 불가능.

아래 페이지에, EFI 시스템에서는 grub2-install 을 쓰지 말라는 주의가 나온다.
내가 겪엇던 grubx64.efi 파일 관련문제에 대한 힌트가 될 수 있겠다.

https://fedoraproject.org/wiki/GRUB_2

grub2-install shouldn't be used on EFI systems. The grub2-efi package installs a prebaked grubx64.efi on the EFI System partition, which looks for grub.cfg on the ESP in /EFI/fedora/ whereas the grub2-install command creates a custom grubx64.efi, deletes the original installed one, and looks for grub.cfg in /boot/grub2/.

결국, 문제의 해답은 아래의 한 줄이었을지도 모르겠다.
상황을 재현하여 실험하면 확인되겠지만.. 같은 일을 또 겪으면 해봐야겠다..

# yum reinstall grub2-efi shim


------

SATA SSD에 설치돼있던 CentOS7을 M.2 NVME 디스크로 옮겨넣고 부팅 시도했더니
루트파티션을 못 찾아 부팅이 안 되는 현상이 생겨서
CentOS7 설치디스크로 부팅한 다음 아래와 같이 initramfs 다시 만들어서 해결함.

# dracut --regenerate-all --force && grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

by 시험さま | 2020/10/26 15:58 | 컴퓨터 | 트랙백 | 덧글(2)
< 이전페이지 다음페이지 >