필수 설치 lib

1. sudo apt-get install ia32-libs libc6-i386 libc6-dev-i386 lib32gcc1

없는것도 있는것 같다. 나와같은 경우 ia32-libs 가 없었다. 그래서 설치방법을
3번과 같은 방법으로 설치했다.

2. 다음과 같은 에러가 뜬다면, 
 /usr/include/features.h:374:25: fatal error: sys/cdefs.h: No such file or directory 
# include <sys/cdefs.h>

설치 : sudo apt-get install libc6-dev-i386

2. 사진파일 참조 - 설치해야함



4. 참조 사진 내 패키지 설치



5.여기서 나온 에러는 다음과 같다. 

/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.a when searching for -lstdc++ 
/usr/bin/ld: cannot find -lstdc++ 

그런데 나에겐 ld 폴더 조차 없었다.. 뭐지?
마지막으로 설치했다.이게 되니 다 되더라.

sudo apt-get install lib32stdc++6
sudo apt-get install lib32stdc++-4.8-dev
sudo apt-get install lib32stdc++6-4.7-dev 
sudo apt-get install lib32stdc++6-4.4-dbg





아래 글은 32bit -> 64bit 에서 변경하면서 생기는 문제점들이다.





변수형의 크기는 어떻게 달라지는가?

int 형은 32bit 를 유지합니다.
short 형은 16bit 를 유지합니다.
long 형은 32bit에서 64bit로 확장됩니다.
long long 형은 64bit 를 유지합니다.
pointer 형은 32bit 에서 64bit로 확장딥니다.
long double 형이 12bytes 에서 16bytes로 확장됩니다.
size_t과 ssize_t 형이 32bit 에서 64bit 로 확장됩니다.
이와 관련된 typedef 문 역시 확장됩니다. 

64bit linux platforms 

Architecture | uname -m | Size | Endian | Libpath | Miscellaneous ----------------+----------+------+--------+---------+-------------------------------- Alpha | alpha | LP64 | little | lib | AMD64 | x86_64 | LP64 | little | lib64 | executes x86 code natively IPF | ia64 | LP64 | little | lib | executes x86 code via emulation MIPS64 | mips64 | LP64 | both | lib64 | executes MIPS code natively PowerPC64 | ppc64 | LP64 | big | lib64 | executes PowerPC code natively Sparc64 | sparc64 | LP64 | big | lib64 | executes Sparc code natively PA-RISC64 | parisc64 | LP64 | big | - | only kernel support, no 64-bit | | | | | executes 32-bit PA-RISC code zSeries (s390x) | s390x | LP64 | big | lib64 | executes s390 code natively 




문제가 되는 코드들 



크기가 다른 변수형에 대한 포인터를 사용한 경우 (스택붕괴가 우려되는 경우) 

getsockopt의 size인자가 socklen_t 로 정의되는 경우 아래의 코드는 s_socklen 변수를 int로 정의한것에서 문제가 발생할수 있습니다.int s_socklen; s_result = getsockopt(s_socket, s_level, s_optname, &s_optval, &s_socklen); 


이것은 다음과 같이 변경되어야 합니다. 이것은 int와 socklen_t 는 크기가 다르기 때문입니다.socklen_t s_socklen; s_result = getsockopt(s_socket, s_level, s_optname, &s_optval, &s_socklen); 


조건식을 int 로 받는 함수에 포인터를 넘겨줄경우 (컴파일러 경고) 일반적으로 다음과 같은 함수가 있을때void my_assert(int s_expression) { if(!s_expression)return; (void)fprintf(stderr, "assert....\n"); } 


위와 같은 함수에 조건문을 사용할때void *s_ptr = NULL; my_assert(s_ptr); 


다음과 같이 변경하여야 합니다. 이것은 포인터가 int 형과 다른 크기이므로 포인터는 int로 casting 되면서 잘리게 되고 NULL포인터가 아님에도 하위 32bit가 0인경우 my_assert 는 의도하지 않은 동작을 할수 있기 때문입니다.void *s_ptr = NULL; my_assert(s_ptr != NULL); 




dword 정의 (만약 이렇게 써왔다면..) 

다음과 같이 my_DWORD를 정의하여 사용했다면#define my_DWORD unsigned long int 

다음과 같이 변경하여야 합니다.#define my_DWORD unsigned int 




x86계열 어셈블리 호환성 (안바꿔도 동작한다.) 

예를 들어서 atomic exchange 를 다음과 같이 C함수로 구현했다면 전혀 수정할 필요없이 그대로 컴파일 가능합니다. 하지만 int형이 아닌 long 형을 사용했다면 register 는 eax, ebx, .. 가 아닌 rax, rbx, ... 로 변경을 고려해야 합니다.int my_atomic_exchange(int * volatile s_to, int s_value) { __asm volatile ("xchgl (%2), %0\n\t" : "=r"(s_value) : "0"(s_value), "r"(s_to) : "memory"); return(s_value); } 




implementation 함수의 잘못된 고려 (size_t 등의 의미를 전혀 활용하지 못한경우 포팅이 쉽지 않을수 있음.) 

예를 들어서 atomic exchange 를 다음과 같이 C함수로 구현했다면 전혀 수정할 필요없이 그대로 컴파일 가능합니다. 하지만 int형이 아닌 long 형을 사용했다면 register 는 eax, ebx, .. 가 아닌 rax, rbx, ... 로 변경을 고려해야 합니다.int my_atomic_exchange(int * volatile s_to, int s_value) { __asm volatile ("xchgl (%2), %0\n\t" : "=r"(s_value) : "0"(s_value), "r"(s_to) : "memory"); return(s_value); } 




정렬 

기존에는 구조체의 sizeof() 에 의한 정렬된 값이 보통 4byte align로 사용되었으나 이것은 이제 기본값으로 믿을수 없습니다. 이제는 보통 8byte align 이 기본값으로 사용됩니다. 때문에 반드시 의도적으로 align을 해야 되는 경우라면 다음과 같이 작성되어야 합니다. (이것은 뻔한 내용이지만 그것을 이야기 하려고 한것이 아니고 신중한 library 개발자라면 모든 구조체는 명시적으로 align 을 지정해줘야 될수 있다는 것을 말합니다.)#pragma pack(push,8) struct ts_my_struct { unsigned char b; unsigned short w; unsigned int d; unsigned long d; unsigned long long q; long double paragraph; } #pragma pack(pop) 



predefine 으로 64bit 를 검출 

각 architecture 별 predefine의 종류가 많아서 간단하게 검출할수 있는 내용은 아니지만 제가 지금까지 포팅한 architecture는 다음과 같이 하여 검출하였습니다. 사실 이것이 모두 완벽하게 검출한다고 할수는 없습니다. 들어보지도 못한 architecture도 많으니까..#if defined(__x86_64__) || defined(__ia64__) || defined(_M_AMD64) || defined(_M_IA64) || defined(_WIN64) || defined(__alpha__) || defined(__s390__) /* ... */ /* 오~ 나 64bit 에서 컴파일 되네.. 어허 요렇게 처리하자~ */ #endif 




캐쉬(cache) 조정 

gcc 사용자라면 64bit 에서 보다 높은 성능을 위하여 __builtin_expect((long)(m_expression),(long)(m_value)) 내장함수도 한번 검토해보시면 좋을것 같습니다. 이것은 조건식이 거의 실행되지 않을 확률 또는 실행될 확률을 조정함으로써 컴파일러로 하여금 Cache 의 최적사용을 위한 최적화가 가능해지도록 유도될수 있습니다. 64bit 기계어 코드를 보시면 이러한 Cache 를 효과적으로 사용할수 있도록 하는 방법이 제공되기 때문에 잘만 사용하면 성능이 극대화 될것으로 생각됩니다.