가이드: 애플 실리콘 Mac에서 x86 프로그램 빌드 및 디버깅하기

윤아 2023-10-09

안녕하세요! POCU 아카데미 수강생 여러분. 윤아입니다!

POCU 아카데미에서 원활한 수강을 위해 권장하는 운영체제는 윈도우이지만 리눅스나 Mac을 사용하셔도 POCU 아카데미의 모든 수업을 들을 수 있답니다!

그런데 최근에 나온 Mac 컴퓨터를 사용하면 COMP2300: 어셈블리 프로그래밍 과목에서 x86 인라인 어셈블리 프로그래밍을 할 때 다소 어려움이 있을 수 있는데요. 그건 최근 Mac 컴퓨터가 사용하는 CPU가 x86 기계어를 실행할 수 없기 때문입니다.

하! 지! 만! POCU 아카데미가 이에 대해 대책도 없이 이 수업을 만들었을 리가 없죠. 엣헴!

그래서 이번 가이드에서는 애플 실리콘 Mac에서 x86 프로그램을 빌드 및 디버깅하는 방법을 소개하겠습니다!

이 글은 macOS 14.0 Sonoma를 기준으로 작성되었음을 미리 알려드립니다.

UTM 설치하기

첫 번째로 할 일은 애플 실리콘 Mac 컴퓨터에서 x86 리눅스 운영체제를 에뮬레이션 할 수 있도록 UTM을 설치하는 것입니다.

  1. 웹 브라우저를 열어 UTM의 v4.3.5 Release 페이지로 갑니다.
  2. Assets에서 UTM.dmg를 다운로드합니다.
  3. 다운로드가 완료되면 UTM.dmg를 더블 클릭합니다.
  4. UTM.appApplications 폴더로 드래그합니다.

x86 가상머신 만들기

다음은 UTM에 x86 가상머신을 만들 차례입니다. 이 가상머신에서 코드를 빌드하고 디버깅할 예정입니다.

  1. 웹 브라우저를 열어 Ubuntu 22.04.3 LTS Jammy Jellyfish 다운로드 페이지로 갑니다
  2. 제일 아래 목록에서 ubuntu-22.04.3-live-server-amd64.iso를 다운로드합니다. 곧바로 다운로드하는 링크
    • 주의: 반드시 Desktop이 아닌 Server 버전을 받으세요. 에뮬레이션 환경에서 Desktop 버전의 그래픽을 그리는 건 매우 느리거든요!
  3. UTM을 실행합니다.
  4. +를 클릭한 뒤, Emulate를 선택합니다.
  5. 운영체제를 고르는 화면이 나오면 Linux를 클릭합니다.
  6. 이제 Browse 버튼을 눌러 앞서 다운로드하였던 .iso파일을 선택한 뒤, Open 버튼을 누릅니다.
  7. Continue 버튼을 누릅니다.
  8. 하드웨어(Hardware) 설정화면에서 아무것도 바꾸지 말고 Continue를 누릅니다.
  9. 드라이브 저장 용량(Storage)을 묻는 화면이 나오면 10 GB로 변경하고 Continue를 누릅니다.
    • 실제 Ubuntu server가 권장하는 용량을 25 GB입니다.
    • 개발을 위해 이것저것 설치하면 실제로는 6 GB 정도 차지합니다.
  10. 공유 디렉터리(Shared Directory) 화면이 나오면 Browse를 눌러 POCU 아카데미에 코드 제출을 위해 설정해 둔 git 저장소의 루트 폴더를 선택합니다.
    (이래야 코드 편집은 내 Mac에서! 빌드 및 디버깅은 가상머신에서 할 수 있답니다!)
  11. Continue를 누른 뒤, Save를 누릅니다.

x86 가상머신에 리눅스 설치하기

다음은 새로 만든 가상머신에 x86 리눅스 운영체제를 설치할 차례입니다. 중간중간 기다려야 할 일이 있으니 재밌는 너튜브나 웹툰을 준비해 두세요

  1. UTM에서 새로 생긴 가상머신 오른쪽에 플레이 버튼이 보일 겁니다. 이 버튼을 눌러 가상머신을 부팅합니다.
  2. GNU GRUB 페이지가 나오면 Try or Install Ubuntu Server를 선택합니다.
  3. 대략 3분 정도 너튜브를 보며 기다립니다.
  4. 언어 선택 페이지가 나오면 English를 선택합니다.
  5. Installer update available 페이지가 나오면 Continue without updating을 선택합니다.
  6. Keyboard configuration 페이지가 나오면 Done을 선택합니다.
  7. Choose type of install 페이지가 나오면 Done을 선택합니다.
  8. Network connections 페이지가 나오면 IP 주소를 자동으로 받아올 때까지 기다린 후(30초 미만) Done을 선택합니다.
  9. Configure proxy 페이지가 나오면 Done을 선택합니다.
  10. Configure Ubuntu archive mirror 페이지가 나오면 This mirror location passed tests라는 메시지가 나올 때까지 기다린 후(30초 미만), Done을 선택합니다.
  11. Guided storage configuration 페이지가 나오면, 아무 옵션도 바꾸지 말고 Done을 선택합니다.
  12. Storage configuration 페이지가 나오면 Done을 선택합니다.
  13. Confirm destructive action 팝업이 나오면 Continue를 선택합니다.
  14. Profile setup 페이지가 나오면 정보를 채워 넣은 뒤, Done을 선택합니다.
  15. Upgrade to Ubuntu Pro 페이지가 나오면 Continue를 선택합니다.
  16. SSH Setup 페이지가 나오면 아무것도 바꾸지 말고 Done을 선택합니다.
  17. Featured Server Snaps 페이지가 나오면 아무것도 바꾸지 말고 Done을 선택합니다.
  18. 이제 설치가 끝나려면 12분 정도 기다립니다. ~~자~ 재밌는 웹툰이라도 몇 편 보고 오자구요!~~
  19. 설치가 끝나고 Reboot now라는 메시지가 나오면, 그냥 x 버튼을 눌러 창을 닫습니다.
  20. UTM에서 내 가상머신을 선택하면 제일 아래쪽에 CD/DVD가 있는데 그걸 Clear 합니다.

후~ 리눅스 설치 과정 정말 길었네요. 아직 조금 더 남았습니다! 우리 모두 힘내봅시다! (^0^)/

가상머신에 공유 폴더 마운트하기

이제 내 Mac에서 코드를 편집하면 가상머신에서 곧바로 빌드할 수 있도록 공유 폴더를 마운트 할 차례입니다.

  1. UTM에서 내 가상머신 오른쪽에 있는 플레이 버튼을 눌러 가상머신을 부팅합니다.
  2. 설치 중에 설정했던 로그인 정보를 사용해서 로그인합니다.
  3. 화면이 멈춘 것 같아 보이면 enter 키를 한 번 치면 프롬프트 창이 나올 겁니다.
  4. cd /media를 입력해 /media로 현재 폴더를 변경합니다.
  5. sudo mkdir pocu를 입력하여 pocu라는 이름의 폴더를 만듭니다. 이 폴더에 공유 폴더를 마운트 할 예정입니다.
  6. sudo mount -t 9p -o trans=virtio share pocu -oversion=9p2000.L를 입력하여 공유 폴더를 마운트합니다.
  7. ls pocu를 입력하여 실제 공유 폴더에 있는 파일들이 잘 보이는지 확인합니다.
  8. sudo chown -R $USER pocu를 입력하여 가상머신에서 이 폴더에 있는 파일들을 수정할 수 있도록 권한을 변경합니다.
  9. 부팅할 때마다 자동으로 이 폴더를 마운트 하려면 다음처럼 설정해 주세요.
    1. sudo vim /etc/fstab을 입력하여 /etc/fstab 파일을 vim 에디터 안에서 엽니다.
    2. i 키를 눌러 편집 모드로 변경합니다.
    3. 화살표 키를 이용하여 제일 마지막 줄로 이동한 뒤, 엔터키를 눌러 새 줄을 만듭니다.
    4. 새 줄에 다음 내용을 입력합니다. share /media/pocu 9p trans=virtio,version=9p2000.L,rw,_netdev,nofail 0 0
    5. esc 키를 눌러 편집 모드를 종료합니다.
    6. :wq를 입력하여 저장 후 vim 에디터를 종료합니다.

x86 가상머신에서 빌드하기

이제 x86 가상머신에 C 컴파일러인 clang을 설치해 보겠습니다. 이 컴파일러를 통해 x86 프로그램을 빌드할 수 있답니다.

  1. sudo apt-get update를 입력하여 패키지 목록을 업데이트합니다.

  2. sudo apt install clang을 실행하여 clang 컴파일러를 설치합니다.

  3. sudo apt install gcc-multilib을 실행하여 32비트용 라이브러리를 설치합니다.

  4. 내 Mac에서 공유 폴더에 main.c 파일을 추가합니다. 내용은 다음과 같습니다.

    #include <stdio.h>
    
    int add(int a, int b)
    {
        int res;
    
        __asm (
            "mov %0,%1\n"
            "add %0,%2\n"
            : "=r"(res)
            : "r"(a), "r"(b)
            :
        );
    
        return res;
    }
    
    int main(void)
    {
        printf("Hello World! %d\n", add(1, 2));
    
        return 0;
    }
    
  5. 가상머신에서 이 프로그램을 빌드합니다. clang -std=c89 -Wall -pedantic-errors -masm=intel -m32 main.c

  6. 이제 ./a.out을 입력하여 프로그램을 실행합니다. 화면에 다음의 결과가 출력될 것입니다. Hello World! 3

x86 가상머신에서 디버깅하기

아무리 천재 프로그래머라도 디버거가 필요할 때가 있죠? LLDB를 사용하면 GUI 없이도 디버깅을 할 수 있답니다.

  1. sudo apt install lldb을 입력하여 LLDB 디버거를 설치합니다.
  2. lldb a.out을 입력하여 LLDB 디버거를 실행합니다.
  3. breakpoint set --name add를 입력하여 add 함수에 중단점(breakpoint)을 설정합니다.
  4. run 혹은 r을 입력하여 프로그램을 실행합니다. add 함수에서 프로그램 실행이 멈출 것입니다.
  5. step 혹은 s를 입력하여 코드를 한 줄 실행합니다.
  6. quit을 입력하여 디버거를 종료합니다.
  7. 이제 -g -O0 컴파일러 옵션을 추가하여 main.c를 다시 빌드한 뒤, 다시 LLDB 디버거를 사용해 봅니다.

마치며

자, 어떠셨나요? POCU 아카데미 수강생 여러분들이라면 큰 문제없이 따라오셨을 거라 생각합니다! 혹시라도 LLDB의 자세한 사용법을 알고 싶으시다면 다음 글들을 참고하세요. ^^

그럼 또 다른 가이드에서 뵐께요~ 모두 즐거운 POCU 되세요~!

img

TOP 개발자에게 배우는 컴공수업 | 수업료는 최저시급, 난 최고연봉 | 프로그래밍 공부순서

야근 없이 오직 실력으로 대우받는 프로그래머가 되고 싶다고요? POCU 아카데미에서 시작하세요!