libc.so는 표준 C라이브러리의 공유 객체 파일(Shared Object File)이다. 솔라리스에서 C 컴파일러로 컴파일 되었다면, 정적으로 컴파일하지 않는한 libc.so파일을 로드하게 된다. ldd /usr/bin/ls를 실행 해보면 가장 기본적인 명령어인 ls(1) 조차도 libc.so를 읽도록 되어있는것을 알 수 있다. 간단히 말해 솔라리스에서 작동하는 모든 프로그램은 libc.so를 사용하고 있다고 해도 과언은 아니다. (솔라리스 10의 초기에는 /sbin 아래의 파일들은 libc.so를 사용하지 않았지만 지금은 호환성 문제로 libc.so 를 사용한다)
1) 이 파일은 솔라리스 11부터 기본제공되지 않으며, system/header 패키지를 설치해야한다.
wl시스템은 prfchw rdseed avx2 rdrand ...을 지원하고 이에 맞춰서 /usr/lib/libc/libc_hwcap1.so.1가 선택되었다.
명령셋
HW1
CMOV
CMOV는 conditional move 라는 의미를 가지는 어셈블리 명령이다.
CMP EAX, EBX
JBE skip
MOV EAX, EBX
skip:
→
CMP EAX, EBX
CMOVA EAX, EBX
CMOVA 는 conditional move if above 라는 뜻의 명령어이다. 위 예제는 EAX와 EBX중 작은 것을 취하는 내용이다. 펜티엄 프로부터 추가되었다.
SEP,AMD_SYSC
※ SEP
Intel CPU에는 SYSENTER,SYSEXIT 명령셋(어셈블리언어 명령어)이 추가되어있다. 이 명령셋은 Fast System Call(SEP)라 부르며 인텔 펜티엄 프로 이상에서 사용 가능하다. (Fast System Call을 사용하기 위해서는 SEP(SYSENTER Present)비트가 반드시 셋 되어있어야 한다)
※ AMD_SYSC
AMD System Call 의 약어. AMD사가 SYSCALL,SYSRET 명령셋으로 Intel의 SYSENTER, SYSEXIT과 동일한 역할을 한다.
※ 쉽게 말해 빠른 시스템콜 호출을 위해 CPU제조사는 독자적인 명령셋을 개발했고 그것이 Intel CPU에서는 SEP, AMD CPU에서는 AMD_SYSC이다. 그리고 솔라리스10 에서는 이를 감지해 사용한다.
FXSR
FXSAVE 와 FXRSTOR (Fast FPU/SIMD state Save/Restore)명령구문을 의미한다. OS와 CPU에서 동시에 지원하면 컨텍스트 스위칭을 빠르게 수행한다. 이 명령셋을 사용하려면 SSE를 지원하는 CPU가 필요하다.
CX16, CX8
cmpxchg16b(Compare and Exchange 16 Bytes)명령구문을 의미한다. CX8(cmpxchg8b)명령의 16 바이트 버전이다. 쉽게말해 CAS(Compare and Swap)연산을 수행한다. 초기의 AMD 64 CPU에서는 오류가 있다. 128비트 부동 소수점 연산시 컨텍스트 스위칭에 대비해 '락'을 걸게 되는데, 이 명령은 LOCK 접두어와 같이 사용해 원자단위 연산(atomic operation)이 가능하도록 하여 (수행 도중 컨텍스트 스위칭 할 수 없음) 결과적으로는 락 없이 연산 가능하도록 한다. 64bit CPU가 필요하다. 쉽게 말해 아래와 같은 구문을 한개의 어셈블리 명령으로 수행한다. 동시성 알고리즘을 구현하기 위한 중요한 명령셋이다.
int __sync_val_compare_and_swap_4b(int *memory_location, int expected_value, int new_value) {
int old_value = *memory_location;
if (old_value == expected_value) {
*memory_location = new_value;
}
return old_value;
}
http://www.ibm.com/developerworks/kr/aix/library/au-multithreaded_structures2/index.html 에서 발췌
AHF
LAHF(Load Status Flags into AH), SAHF(Store AH into Flags) 명령어다. 기본적인 산술 플래그(SF, ZF, AF, PF, CF )를 AH에 저장하거나 AH에서 로드한다. 인텔의 초기 64bit 프로세서에서 오류가 있었기도 하다.
TSCP, TSC
RDTSCP(Read Time-Stamp Counter and Processor ID), RDTSC(Read Time-Stamp Counter)명령이다. 전자는 64비트 타임스탬프와 32비트 IA32_TSC_AUX 값을 EDX:EAX, ECX에 넣는다. 후자는 프로세스 아이디를 로드하지 않는다.
POPCNT
POPCNT(Population count)명령이다. 2진 표현에서 1의 개수를 세는 명령이다. 데이터 분석, 데이터 암호화에 주로 사용된다.
LZCNT
LZCNT(Leading zero count)명령이다. 2진 표현에서 앞에 0이 몇개인지 세는 명령이다. AMD CPU에서만 지원되다가 인텔 하스웰 프로세서부터 지원해준다. (BMI1 에 포함되어있다)
MOVBE
MOVBE(Move Data After Swapping Bytes)명령이다. 인텔 하스웰 프로세서부터 지원해준다.
AES
AES 암호화(AESENC, AESENCLAST), AES 복호화(AESDEC, AESDECLAST), AES 키 생성(AESIMC, AESKEYGENASSIST)을 위한 명령셋이다. 하드웨어 AES는 소프트웨어 AES를 해킹할 때 사용되는 몇가지 공격 기법(Data-Independent Time 연산과, Lookup Table, Cache Attacks 등등)을 근본적으로 차단하기 때문에 안정성과 보안 면에서도 더 좋다. 인텔의 경우 클락데일 프로세서의 일부 부터, AMD의 경우 불도저 아키텍처를 사용한 프로세서부터 사용 가능하다.
PCLMULQDQ
PCLMULQDQ(Performs a carry-less multiplication of two 64-bit integers)명령이다. CRC32, AES GCM, LZ77 Sliding Window DEFLATE 계산시 사용할 수 있다.
XSAVE, XRSTOR
XSAVE(Save Processor Extended States), XRSTOR(Restore Processor Extended States)명령이다. FXSAVE/FXRSTOR 를 확장한 명령이다. FXSAVE는 FPU, MMX, SSE 레지스터만을 담는 반면, XSAVE는 FPU운영 레지스터와 MXCSR레지스터도 담는다. 펜린의 최신 스테핑 및 불도저 이후의 프로세서에서 사용할 수 있다.
비슷한 구문으로 OSXSAVE 기능이 있는데 이는 XSETBV/XGETBV 명령셋을 의미한다.
XOP
XOP(eXtended Operations)는 AMD CPU에서 사용할 수 있는 명령이다. SSE5(취소됨)에서 추가되었던 명령셋이다. AVX, FMA4, CVT16과 비슷한 기능을 한다.
FMA4
FMA(fused multiply add)명령셋중 4개의 오퍼랜드를 취하는 명령어다. $0 = $1×$2 + $3 형태의 연산을 수행한다. AMD의 불도저이후의 CPU에서만 사용 가능하다.
HW2
RDRAND
Intel Secure Key 지원을 위한 RDRAND 명령셋을 의미한다. DRNG구현을 위해 필요한 명령셋이다. 이 명령셋은 인텔의 아이비브릿지 프로세서부터 지원한다. 이후에 좀 더 보완한 RDSEED 명령도 있다.
FMA
Intel 의 FMA(fused multiply add)명령셋중 3개의 오퍼랜드를 취하는 명령셋을 의미한다. FMA3 라고도 불린다. $0 = $0×$2 + $1, $0 = $1×$0 + $2, $0 = $1×$2 + $0와 같은 형태의 연산을 수행한다. 인텔 하스웰 프로세서, AMD의 경우 파일드라이버 이후의 프로세서부터 지원한다.
F16C
F16C 명령셋을 의미한다. 한때 CVT16라고도 불렸다. 16바이트(128비트) 부동소수점 연산을 지원해준다.
TBM
TBM(Trailing Bit Manipulation)명령셋을 의미한다. 비트연산을 빨리 하기 위한 명령셋으로 AMD 파일드라이버 프로세서부터 지원한다. 아래의 BMI와 유사한 명령도 있다.
BMI1, BMI2
BMI명령셋을 의미한다. 이 명령셋은 빠른 비트연산을 지원해준다. BMI1에서는 비트연산을 지원하는 6개의 명령어가 추가되었다. AMD의 ABM을 향상시킨 명령셋이다. AMD의 파일 드라이버 프로세서부터, 인텔의 하스웰 프로세서부터 지원한다.
BMI2는 솔라리스 11.2부터 지원되며, 8개의 명령어가 추가되었다. 하스웰부터 지원되며, AMD의 경우 Excavator 아키텍처(2014.04 현재 미 출시)부터 지원될 예정이다.
FSGSBASE
FSBASE, GSBASE 레지스터에 읽기/쓰기를 위한 명령셋이다. RDFSBASE, RDGSBASE, WRFSBASE, WRGSBASE 명령이 그것으로, 빠른 컨텍스트 스위칭, LWP와 관련 있다. 기존에는 SWAPGS 명령셋을 통해 간접적으로 제어하던 것을 직접적으로 제어하도록 변경되었다. 인텔 아이비 브릿지 프로세서부터 지원한다.
HLE
Intel HLE에서 사용하는 XACQUIRE, XRELEASE 접두어를 의미한다. (명령셋이 아니다) 하위호환을 위해 이 접두어는 하위호환을 위해 REPNE, REPE 접두어의 옵코드를 재사용한다. HLE를 구현한다. 인텔 하스웰 프로세서부터 구현되었는데 버그로 인해 인텔의 마이크로코드 업데이트로 비활성화 시켰다. 이후 2014년 11월 출시된 Broadwell-Y 시리즈의 F-0 스태핑부터 해결되어 출시되었다.
RTM
Intel RTM을 지원하기 위한 XBEGIN, XEND, XABORT, XTEST 명령셋을 의미한다.
EFS
EFS 지원 여부. Enhanced REP MOVSB/STOSB 라고도 한다. Ivy Bridge CPU부터 지원한다. MOVSB(move single byte)는 [DS:ESI]에서 [ES:EDI]으로 한 바이트를 이동하는 명령이다. REP MOVSB명령에서 REP는 Repeat 의 의미를 지니는데, 이를 ECX에 있는 회수만큼 반복하라는 의미다. 처음 소개되었을 당시에는 빠른 명령이었으나, 지금은 다른 방법으로 더 빠르게 복사가 가능해졌다. 이를 해결한 것이 EFS다.
RDSEED
RDSEED 명령셋을 의미한다. 난수를 생성하기 위한 명령셋이다. PRNG의 시드를 생성하기 위해 사용할 수 있다. 비 결정적 랜덤 비트 발생기로, RDRAND와는 다르다. 인텔 브로드웰 프로세서부터 지원한다.
ADX
Intel ADX지원을 위한 명령셋을 의미한다. ADCX, ADOX 명령이 그것이다. 인텔 브로드웰 프로세서부터 지원한다.
PREFETCHW
PREFETCHW 명령셋을 의미한다. L1 데이터 캐시로 32바이트를 Prefetch 하는 명령어가 PREFETCH 이다. AMD의 3D Now 확장부터 PREFETCH/PREFETCHW 명령으로 지원하던 명령어인데, 동일한 기능을 하는 PREFETCHh 명령이 인텔프로세서에서 지원되다가 PREFETCHW 명령이 인텔 브로드웰부터 지원된다.
AVX512
AVX 명령셋의 512비트 확장. AVX512 는 AVX 나 AVX2 와는 달리 CPU에 따라 지원하는 명령어셋이 세분화되어있는데, 이에 따라 각각의 명령셋 지원여부를 알아내여 구현해야 한다.
VP2INTERSECT(Vector Pair Intersection to a Pair of Mask Registers)
4FMAPS(Fused Multiply Accumulation Packed Single precision)
4VNNIW(Vector Neural Network Instructions Word variable precision)
BF16(Brain Floating Point)
PRFCHWT1
PREFETCHWT1 명령셋을 의미한다. 벡터 데이터까지 캐시할 수 있으며, T1 힌트도 제어한다.
MPX
Intel 의 Memory Protection Extensions 과 그 확장 명령을 의미한다. BND0 ~ BND3, BNDCFGU, BNDCFGS, BNDSTATUS 레지스터를 제어하며, BNDMK, BNDCU, BNDLDX, BNDSTX 명령이 있다.
SGX
Intel Software Guard 와 그 확장 명령을 의미한다.
SHA1, SHA256
Intel SHA-1, Intel SHA-256 를 지원하는 SHA1RNDS4, SHA1NEXTE, SHA1MSG1, SHA1MSG2, SHA256RNDS2, SHA256MSG1, SHA256MSG2 명령셋을 의미한다.
CLWB
Intel CLWB(Cache Line Write Back) 명령 셋을 의미한다. 이전까지는 CLFLUSH 명령(CPU 의 L1 ~ L3 캐시 플러싱)만 사용하는 정도였다면, NVRAM 이 나오면서 이젠 보조기억장치(HDD, SSD, ...)도 메모리만큼 빨라졌는데, 그렇다면 중간에 버퍼가 필요 없어진다. CLFLUSH는 캐시라인을 비우기 때문에 (더이상 캐시가 되지 않기 때문에) 캐시라인만 안 비우고 플러싱 해주는 CLWB가 나왔다.
PCOMMIT
Intel PCOMMIT 명령셋을 의미한다. CLWB과 목적이 비슷하다. CLWB가 CPU 의 캐시만 플러싱 해주었다면 PCOMMIT 은 NVRAM 까지 플러싱 해준다. 2016년 이후 더이상 사용되지 않는다.
HW3
WAITPKG
Intel WAITPKG 명령셋을 의미한다. UMONITOR, UMWAIT, TPAUSE 이다. UMWAIT 는 User Level Monitor Wait 으로 불린다.
GFNI
Galois Field New Instructions.
VAES
Vector AES instructions. VAESDEC, VAESDECLAST, VAESENC, VAESENCLAST 명령셋을 의미한다.
VPCLMULQDQ
carry-less multiplication of quadwords. VPCLMULQDQ 명령셋을 의미한다.
RDPID
RDPID 는 Read Processor ID 명령셋을 의미한다.
MKTME
MKTME 는 Multi-Key Total Memory Encryption 명령셋을 의미한다.
PCONFIG
PCONFIG 는 MKTME 을 위한 설정에 사용되는 명령셋이다.
WBNOINVD
WBNOINVD 는 Write Back and Do Not Invalidate Cache 를 위해 사용되는 명령셋이다.
root@wl ~ # df -k
/usr/lib/libc/libc_hwcap1.so.1
50423874 7450881 42468755 15% /lib/libc.so.1
root@wl ~ # ls -al /usr/lib/libc/libc_hwcap1.so.1 /lib/libc.so.1 1)
-rwxr-xr-x 1 root bin 1087992 9월 18일 02:00 /lib/libc.so.1
-rwxr-xr-x 1 root bin 1087992 9월 18일 02:00 /usr/lib/libc/libc_hwcap1.so.1
root@wl ~ # digest -a md5 /usr/lib/libc/libc_hwcap1.so.1
30fc278a5f38f9141be68b1d83ae70f0
root@wl ~ # digest -a md5 /lib/libc.so.1
30fc278a5f38f9141be68b1d83ae70f0
root@wl ~ # umount /lib/libc.so.1 2)
root@wl ~ # ls -al /usr/lib/libc/libc_hwcap1.so.1 /lib/libc.so.1 3)
-rwxr-xr-x 1 root bin 1083760 9월 18일 01:59 /lib/libc.so.1
-rwxr-xr-x 1 root bin 1087992 9월 18일 02:00 /usr/lib/libc/libc_hwcap1.so.1
root@wl ~ # mount -O -F lofs /usr/lib/libc/libc_hwcap1.so.1 /lib/libc.so.1 4)
1) 두 파일이 같은 파일임을 알 수 있다. 시스템에 따라 /usr/lib/libc/libc_hwcap2.so.1 와 연결되어있을 수 있다. 그렇다면 이 예제에서는 파라메터를 바꿔서 시험해봐야 한다. 2) 마운트를 해제한다. 3) 두 파일이 다른 파일임을 알 수 있다. 파일 용량부터 차이난다. 원래 있는 파일을 지우지 않기 위해 lofs를 이용해 마운트한 것이다. 4) 다시 원래대로 복구한다.
솔라리스의 라이브러리
libCrun, libCstd
libCrun 은 C++ 런타임(new, delete, exception, RTTI 등을 처리)이고, libCstd 은 솔라리스의 C++ 표준 라이브러리다. CC는 기본적으로 사용자가 -xnolib 옵션을 주지 않으면, -lCstd -lCrun -lm -lc으로 간주해 기본 라이브러리를 사용한다.
솔라리스에서는 C++ 라이브러리를 몇가지 제공하는데, -library=Cstd 와 -library=stlport4, -library=stdcxx4 이 그것이다. 서로 호환 안된다.
C++로 만든 C라이브러리는, C에서 컴파일할 때 -lCrun 옵션을 반드시 줘야 컴파일 된다. CC -staticlib=Crun옵션을 줘서 정적으로 컴파일 해도 된다.
root@wl ~/src # cc -g -o libc_0 libc_0.c
root@wl ~/src # ./libc_0
세그멘테이션 결함(Segmentation Fault) (core dumped)
139 root@wl ~/src # dbx libc_0 core
For information about new features see `help changes'
To remove this message, put `dbxenv suppress_startup_message 7.9' in your .dbxrc
Reading libc_0
core file header read successfully
Reading ld.so.1
Reading libc.so.1
program terminated by signal SEGV (no mapping at the fault address)
0xfee663dc: strlen+0x000c: movl (%eax),%edx
Current function is main
12 printf("NULL String: %s\n", str);
(dbx) examine str
0x00000000: dbx: core file read error: address 0 not in data space
(dbx) exit
소스를 수정하는 것이 가장 좋지만, 여의치 않을 경우 0@0.so.1 을 미리 로드 시켜 실행시켜 주면 된다. 하지만 이렇게 하면 몇가지 솔라리스 툴을 사용하는데 있어 제약이 따른다. 예를 들어 truss를 실행시킬 수 없다.