3P by GN⁺ | ★ favorite | 댓글 1개
  • rev.ng는 디컴파일러 백엔드 revng-c를 공개해 디컴파일 엔진을 오픈 소스로 전환하고, UI 비공개 베타·새 웹사이트·rev.ng Hub·문서를 함께 내놓음
  • 로컬에서는 설치 스크립트로 CLI를 구성한 뒤 revng artifactrevng ptml을 사용해 유효한 C 코드 형태의 디컴파일 결과를 확인할 수 있음
  • 인터랙티브 UI는 VSCode 기반으로 브라우저와 독립 실행 앱을 목표로 하며, 뉴스레터 구독자를 FIFO 방식으로 초대하는 비공개 베타에서 제공됨
  • 자동 자료구조 복구, 협업 리버싱, 다양한 아키텍처 지원, 확장성이 핵심 목표지만 현재 QA는 Linux x86-64 바이너리에 가장 집중됨
  • 프레임워크와 CLI는 오픈 소스이고, 클라우드 UI는 공개 프로젝트에 무료 제공되며 비공개 프로젝트·오프라인 독립 실행 UI는 유료 모델로 구분됨

오픈 소스 전환과 비공개 베타

  • rev.ng는 디컴파일러 백엔드인 revng-c를 오픈 소스로 공개함
    • 이 공개로 전체 디컴파일 엔진이 오픈 소스가 됨
    • 초기 문서도 함께 제공됨
  • UI는 뉴스레터 구독자를 대상으로 비공개 베타 초대를 시작할 예정임
    • 초대는 FIFO 방식으로 진행됨
    • 베타 참여를 위해 뉴스레터 등록이 필요함
  • 새 웹사이트와 rev.ng Hub도 함께 공개됨
    • rev.ng Hub는 클라우드 버전 진입점임
    • 베타 사용자는 프로젝트를 만들고, 브라우저에서 UI를 실행하고, 다른 사용자와 협업할 수 있음
    • 비공개 베타 대상자가 아니어도 공개 프로젝트는 둘러볼 수 있음
  • rev.ng 기능을 직접 확인하려는 사용자를 대상으로 비공개 데모도 진행함

CLI로 rev.ng 사용해 보기

  • revng는 root 권한 없이 단일 디렉터리에 설치할 수 있고, 해당 디렉터리를 삭제하면 제거됨
curl -L -s https://rev.ng/downloads/revng-distributable/master/install.sh | bash
cd revng
source ./environment
  • 예제 example.cargc * 3을 반환하는 간단한 프로그램임
int main(int argc, char *argv[]) {
  return argc * 3;
}
  • gcc로 컴파일한 뒤 revng artifact를 실행하면 단일 파일 형태의 디컴파일 결과를 얻을 수 있음
gcc example.c -o example -O2
revng artifact \
        --analyze \
        --progress \
        decompile-to-single-file \
        example \
        | revng ptml --color \
        | grep -A2 -B1 '[^_]main\b' \
        > decompiled.c

베타 범위와 테스트 대상

  • UI를 사용하려면 뉴스레터에 등록해야 하며, 초대는 작은 배치로 진행됨
  • 이번 릴리스는 UI와 디컴파일 결과를 일부 바이너리에서 데모하고, 실제 바이너리 작업에 대한 피드백과 버그 리포트를 받는 데 초점을 둠
  • 테스트에 사용한 비단순 바이너리와 .text 크기는 다음과 같음
  • rev.ng는 여러 ABI와 플랫폼을 지원하지만, 이 단계의 초기 QA는 Linux x86-64 바이너리에 집중됨
  • 문제가 생기면 Discourse에서 도움을 받을 수 있음

rev.ng가 목표로 하는 디컴파일 경험

  • rev.ng의 주요 초점은 자동 자료구조 복구, 현대적인 UX, 협업 리버싱, 넓은 플랫폼 지원, 확장성임
  • 자동 자료구조 복구

    • Data Layout Analysis로 struct 레이아웃을 프로시저 간 분석을 통해 자동 복구할 수 있음
    • 연결 리스트 노드 예제는 int64_t data[5] 배열과 다음 노드 포인터를 가진 구조체를 대상으로 함
    • rev.ng 출력은 배열 크기 5와 다음 원소 포인터 접근을 자동 감지한 구조체와 함수 코드를 생성함
    • 디컴파일러 출력은 문법적으로 유효한 C 코드임
    • 이 기능은 현재 사용 가능함
  • VSCode 기반 인터랙티브 UI

    • UI는 VSCode 기반이라 VSCode 사용자는 익숙한 방식으로 접근할 수 있음
    • 브라우저 탭과 독립 실행 애플리케이션 양쪽에서 실행될 수 있음
    • 주요 단축키는 다음과 같음
      • Ctrl + Click: 커서 아래 함수나 타입 정의로 이동
      • N: 이름 변경
      • Y: 타입 편집
      • X: 참조 표시
    • rev.ng는 변경이 생기면 영향을 받는 부분만 다시 계산하는 인터랙티브 디컴파일러
    • UI는 현재 비공개 베타 참가자에게 제공됨
  • 협업 리버싱

    • rev.ng UI는 클라이언트-서버 아키텍처를 사용함
    • 여러 사용자가 같은 데몬 인스턴스에 접속해 같은 프로젝트에서 동시에 작업할 수 있음
    • 클라우드 버전에서는 프로젝트 관리를 위한 GitHub 유사 애플리케이션인 rev.ng Hub를 사용할 수 있음
    • 협업 기능은 동작하지만 사용자 경험 개선이 필요하며, 로드맵 항목 #797에서 추적됨

아키텍처와 플랫폼 지원 방식

  • rev.ng는 QEMU 파이프라인의 앞부분을 사용해 실행 코드를 tiny code로 리프트하고, 이를 LLVM IR로 변환한 뒤 디컴파일을 진행함
  • 이 구조 덕분에 QEMU가 지원하는 아키텍처를 비교적 쉽게 지원할 수 있음
  • 아키텍처 지원만큼 플랫폼, 특히 ABI 지원도 중요함
    • rev.ng는 ABI 속성을 선언적으로 기술하기 위해 ABI description format을 사용함
    • 이 형식은 새 ABI 지원을 쉽게 만들 만큼 일반적으로 설계됨
  • 현재 지원 상태는 다음과 같음
    • 아키텍처: x86, x86-64, ARM, AArch64, MIPS, s390x를 서로 다른 성숙도로 지원
    • 바이너리 형식: ELF, PE/COFF, Mach-O 지원
    • 가져오기: .idb, DWARF 디버그 정보, PDB 디버그 정보 지원
  • 대부분의 QA는 Linux x86-64 바이너리에서 수행됐고, 나머지는 추가 QA가 필요함
  • 더 많은 플랫폼 QA는 로드맵 항목 #58에서 추적됨

확장성과 스크립팅

  • rev.ng는 리버스 엔지니어링 도구를 위한 프레임워크를 목표로 하며, 인터랙티브 UI를 제외한 전체 프로젝트가 오픈 소스임
  • 프로젝트 파일인 model은 YAML 문서라 JSON이나 YAML을 파싱할 수 있으면 rev.ng를 스크립팅할 수 있음
  • 모델에는 디컴파일 대상 바이너리의 아키텍처, 기본 ABI, 세그먼트, 함수 목록, 타입 목록 등이 포함됨
  • Python과 TypeScript용 래퍼로 모델을 수정할 수 있음
    • 현재 모델 조작 래퍼는 있지만, 분석 실행과 아티팩트 가져오기를 쉽게 수행하는 방식은 아직 없음
    • 완전한 Python 클라이언트는 로드맵 항목 #17에서 추적됨
  • 내부 표현에는 LLVM IR이 많이 사용되어 LLVM 생태계 도구를 활용할 수 있음

오픈 소스 CLI와 유료 UI의 구분

  • rev.ng 프레임워크는 완전히 오픈 소스이며, CLI에서 원하는 대상을 디컴파일할 수 있음
  • UI 제공 형태는 세 가지로 나뉨
    • 공개 프로젝트용 클라우드 UI는 무료 사용 가능
    • 비공개 프로젝트용 클라우드 UI는 구독 필요
    • 완전 독립 실행·완전 오프라인 UI는 유료로 제공
  • 클라우드 사용 방식은 다음과 같음
    • rev.ng Hub에서 프로젝트를 만들고 협업자를 초대함
    • UI는 브라우저에서 실행됨
    • 백엔드는 rev.ng 클라우드에서 실행됨
  • 프로젝트 파일을 공개해도 괜찮다면 UI를 포함한 클라우드 버전 rev.ng를 무료로 사용할 수 있음
  • Kubernetes를 사용하는 온프레미스 프라이빗 클라우드 서비스 설치도 논의 가능함

1.0 로드맵과 연락 채널

  • 1.0까지의 로드맵은 4개 티어로 나뉨
    • Tier 1: 알파 버전, 지인 대상 데모, 완료됨
    • Tier 2: 베타 버전, 뉴스레터 구독자에게 클라우드 버전 접근 제공, 현재 시작됨
    • Tier 3: 오픈 베타, 예정
    • Tier 4: 1.0 릴리스, 예정
  • 자세한 진행 상황은 로드맵 페이지에서 확인할 수 있음
  • 프로젝트 소식과 지원 채널은 다음과 같음

댓글과 토론

Hacker News 의견들
  • 가격 모델은 rev.ng 프레임워크가 완전 오픈소스이고, CLI에서는 무엇이든 디컴파일할 수 있다는 구조임
    UI는 공개 프로젝트에는 클라우드에서 무료, 비공개 프로젝트에는 클라우드 구독, 완전 독립형 오프라인 앱은 유료로 제공될 예정임
    비교하면 Hopper는 1년 업데이트 포함 100달러이고 https://www.hopperapp.com/index.html, Ghidra와 Radare2는 자유·오픈소스라 완전히 무료이며 IDA Pro는 매우 비쌈

    • Binary Ninja도 좋은 선택지임
      써본 바로는 IDA와 꽤 비슷하지만 더 사용자 친화적이고, 생산성을 높여주는 잘 설계된 기능이 많았음
      Hopper는 안 써봤지만 Ghidra와 Radare2는 개발 경험이 별로였고 생성된 C 코드도 잘 읽히지 않았음. 다만 둘 다 몇 년 전에 써본 기준임
      Binja는 300달러, 상업용은 1500달러이고 학생 할인도 있음: https://binary.ninja/features
    • 디컴파일은 IDA/Ghidra에서 가장 덜 중요하고 덜 신뢰할 수 있는 부분인 경우가 많아서 둘을 단순 비교하는 건 불공평함
      그래도 좋은 C 디컴파일러는 늘 부족하니 새로운 시도는 언제나 반가움
    • 일회성 결제와 정해진 업데이트 기간 라이선스 모델을 정말 좋아함
      다만 앱이 인터넷 접속을 필수로 만들지 않으면서 그걸 어떻게 강제하는지 궁금함
  • 팀 페이지 https://rev.ng/about와 코드 기여 https://github.com/revng/revng/graphs/contributors를 보면, CEO(aleclearmind) 가 CTO(pfez)보다 훨씬 많은 커밋을 가진 게 조금 특이해 보임
    다른 CEO들은 코딩할 시간이 거의 없다고 자주 말하고, CTO도 보통은 관리 쪽이 많고 실제 코딩은 덜 하는 편임
    그래도 이 방식이 잘 돌아간다면 팀 입장에서는 꽤 재미있을 것 같음. 수정: 타임라인을 확인하지 않았음

    • CTO는 주로 방금 공개한 디컴파일러 백엔드 revng-c에서 작업함: https://github.com/revng/revng-c/commits/develop/
      결국 두 저장소를 합칠 예정임
      그리고 나는 매일 개발하고 있는데, 어떤 이유인지 GitHub가 내 사용자를 제대로 잡지 못하고 있음
      실제로도 재미있음
    • CTO가 더 최근 커밋을 많이 했고, aleclearmind의 커밋은 2020년 이후 0으로 떨어져서 그쪽도 코딩 시간을 내기 어려워진 것 같음
    • 비판하려던 건 전혀 아니었는데 왜 다운보트를 받았는지 조금 궁금함
      오히려 이런 모습이 마음에 들었고, 다른 곳에서 본 것과 달라서 흥미로웠음
      흥미롭지 않거나 특이하지 않아서 다운보트된 건가?
  • 현존하는 최고의 프로그래밍 언어 이론 책 중 하나에서 힘을 얻은 멋진 회사로 보임: https://link.springer.com/book/10.1007/978-3-662-03811-6
    “그는 공범이 될 Pietro도 만났다. 꽤 낭만적으로도, 회사의 토대가 될 책 덕분에 그를 만났다.”
    https://rev.ng/about

    • 그 책에 얽힌 전체 이야기는 이렇다. 컴파일러를 공부하기 시작했지만 이론이 너무 어려웠고, 유명한 책들도 내게는 맞지 않아서 꽤 낙담하고 있었음
      그러다 조밀하지만 명확해 보이는 이 책을 발견했고, 지도교수에게 사도 되냐고 물었더니 “먼저 대학 도서관을 확인해봐라”라고 했음
      도서관에 사본이 있었지만 이미 대출 중이었고, 컴파일러 연구를 하는 유일한 그룹에 있던 나는 “우리 그룹 밖에서 누가 감히 컴파일러를 하지?”라는 생각이 들었음
      도서관에 가서 누가 빌렸는지 물었지만 개인정보라 알려줄 수 없다고 했고, 성의 세 번째 글자와 이름의 두 번째 글자만 물어 Z와 I를 얻어냄
      여기서 찾아냈음: https://www.deib.polimi.it/ita/personale-lista-alfabetica
      시간이 흘러 친구가 되었고 함께 회사를 시작함
      출시까지 정말 많은 작업이 필요했음
  • 코드가 변수와 구조체 멤버를 어떻게 다루는지를 바탕으로 변수명과 구조체 멤버명을 자동으로 붙이면 좋겠음
    예를 들어 연결 리스트의 다음 포인터는 next로 식별하기 쉬워야 함
    GitHub 전체를 내려받아 코드에서 레이아웃과 상호작용이 가장 비슷한 변수를 찾고, 신뢰도가 충분히 높으면 그 이름을 쓰는 방식이 가능해 보임

    • 예전에는 이런 걸 수작업으로 해보려고 했음
      예를 들어 유도 변수를 감지하면 i로 이름을 바꾸는 식임
      하지만 지금은 이런 일의 올바른 방식이 LLM을 쓰는 것처럼 꽤 명확해 보임
      다만 현 단계에서 우리는 견고한 기반을 만드는 사람들에 가깝고, 기반이 갖춰지면 기성 모델로 이름을 바꾸거나 주석을 추가하는 건 비교적 쉬움
      핵심은 100% 정확도가 필요한 어려운 디컴파일 작업은 우리가 하고, 이름·주석처럼 근사치가 허용되는 부분에는 LLM을 도입할 수 있다는 것임
      어쨌든 이름을 바꾸는 스크립트 작성은 꽤 쉬우니 문서를 보면 됨: https://docs.rev.ng/user-manual/model-tutorial/
    • 정말 멋질 것 같고, http://jsnice.org/ 같은 느낌임
      JSNice가 내부에서 무엇을 하는지 설명하는 논문: https://files.sri.inf.ethz.ch/website/papers/jsnice15.pdf
    • Binary Ninja의 sidekick과 비슷하게 들림
    • 리버싱용 GitHub Copilot 같은 건가?
  • ELF 파일에서는 동작하지 않음
    ./revng artifact --analyze --progress decompile-to-single-file ../maytag.ko를 실행하면 Only ELF executables and ELF dynamic libraries are supported가 나오고, 파일은 ELF 64-bit LSB relocatable, x86-64, version 1 (FreeBSD), not stripped로 나옴
    FreeBSD 바이너리를 지원하지 않는 건가?
    수정: 커널 모듈을 지원하지 않는다는 걸 놓쳤고, FreeBSD 때문이라기보다 단순 실행 파일이 아니라서 그런 듯함

    • GitHub에 이슈를 열고 바이너리를 첨부해줄 수 있나?
      이걸 로드하는 건 그렇게 어렵지 않을 것 같음
  • 협업 워크플로에 많은 관심이 갔으면 좋겠음
    IDA Teams 같은 건 써보지 않았지만, Google Docs처럼 마찰 없는 리버스 엔지니어링 경험이 가능하면 굉장할 것 같음

    • 그게 우리 목표임
      예전에는 UI 기반으로 QtCreator를 썼는데 끔찍한 선택이었음
      이후 VSCode로 바꿨고, 마침 브라우저에서도 실행 가능했음
      그래서 Kubernetes를 약간 섞어 완전 독립형과 정확히 같은 사용자 경험을 가진 클라우드 디컴파일러를 만들었음
      협업 부분은 아직 QA가 더 필요하지만 기본적으로 동작함
      데몬 하나에 여러 클라이언트라는 아주 단순한 구조임
      예전에 CTF에서 서버의 X 세션 위에 IDA 창 여러 개와 커서 여러 개로 “협업”하던 경험에서 영감을 얻은 것 같음. 매우 저주받은 방식이었지만 효과는 있었음
  • 타입 추론을 지원할 계획이 있나?
    현재는 모든 변수가 generic64_t로 보이는 것 같은데, Ghidra처럼 타입을 자동 감지하면 좋겠음. 물론 Ghidra도 가끔 틀리긴 함

  • 흥미로워 보임
    완전 독립형 버전을 써보고 싶음
    대략적인 가격 소식이 있나? 취미 사용자도 감당할 수 있을 정도면 좋겠음

  • 바이너리 해킹 도구가 늘어나는 건 언제나 반가움
    직접 써보고 싶을 수도 있어서, 선택한 패키징 형식에 대해 지나치게 세밀한 제안을 남김
    source ./environment는 좋지 않은 징조임. tar를 받아보니 실제로 PATH를 포함한 여러 환경 변수를 설정했고, 다행히 LD_LIBRARY_PATH는 아니었음
    대부분 HARD_ 접두사인데 아마 고유하겠지만 REVNG가 더 명확해 보이고, 기존 환경 변수와 충돌하는 건 나쁨
    AWS_EC2_METADATA_DISABLED="true"도 설정하는데, 나는 AWS를 안 써서 깨지진 않지만 일반적으로는 의심스러움
    RPATH_PLACEHOLDER, HARD_FLAGS_CXX_CLANG, 긴 PATH, mingw32/gentoo/mips 문자열 등은 취약해 보임
    실행 안내에 “이제 환경 변수를 바꾸라”가 있으면 보통 포기하는데, 비 Ubuntu 시스템에서 제대로 동작하지 않는 프로그램과 강하게 상관되어 있음
    애플리케이션 제어 흐름을 실행 환경에 엮으면 처음 보이는 것보다 실패 모드가 많고, 전역 변수와 매우 비슷함
    Clang은 빌드 시 -DCLANG_DEFAULT_CXX_STDLIB=libc++ 같은 기본값을 구워 넣을 수 있고, DEFAULT_SYSROOT도 유용함
    rpath를 쓰더라도 사용자가 LD_LIBRARY_PATH를 설정한 상태에서 실행하면 바이너리의 DT_RUNPATH가 덮일 수 있음
    요즘 -Wl,rpath는 실제로 rpath가 아니라 덜 유용한 runpath를 의미하고, 아마 원하는 호출은 -Wl,rpath -Wl,--disable-new-dtags라서 로더가 라이브러리 탐색 시 LD_LIBRARY_PATH를 무시하게 하는 것임
    Clang 빌드 플래그, 정적 링크, 바이너리 안에 바이너리 내장 등을 조합하면 환경 변수 조작을 완전히 없앨 가능성이 큼
    clang-16 바이너리가 동적 링크되어 런타임에 libLLVMAArch64CodeGen.so.16 같은 것을 찾는 것도 실패 모드를 늘림
    LLVM_BUILD_STATIC=ON이면 HPC 모듈 툴체인이 활성화된 환경에서 엉뚱한 라이브러리를 집어드는 문제를 줄일 수 있음
    도구들이 libc++.so, libc++abi.so 등에 링크되어 있는데, 정적 libc++를 고려할 만하고, 최소한 libc++abilibunwind는 libc++ 안에 정적으로 링크하는 편이 좋음
    Linux에서 동적 링크 프로그램을 배포하는 데 인내심이 완전히 바닥났음
    README의 source ourhack나 모듈 시스템이 남긴 환경 변수가 내 애플리케이션의 런타임 라이브러리를 바꿔버리면 사용자 경험과 이후 버그 리포트 비용이 끔찍해짐
    그에 비해 정적 링크는 정말 좋음

    • 환경을 건드리는 것에 대한 우려 대부분은 실제로 source environment를 한다는 가정에서만 맞음
      사실 그걸 제안한 이유는 데모 바이너리용으로 우리가 배포하는 GCC를 쓰게 하려는 것뿐이고, 의도된 사용 방식은 ./revng 스크립트임
      이 경우 환경 변경은 revng 호출에만 영향을 줌
      문서는 여기 있음: https://docs.rev.ng/user-manual/working-environment/
      source ./environment에 대한 경고를 추가하는 게 좋겠음
      LD_LIBRARY_PATH는 쓰지 않으려고 많은 시간을 들였고, 각 ELF가 상대 경로로 의존성을 참조하는 완전 자기완결 바이너리 세트를 만들었음. LD_LIBRARY_PATH는 악임
      HARD_ 변수는 컴파일러 래퍼에서만 쓰이고 실제로 충돌할 가능성은 거의 없다고 봄
      AWS_EC2_METADATA_DISABLED="true"의 원래 논의는 https://github.com/revng/revng/pull/309#discussion_r12805759...에 있음
      AWS SDK를 패치해 피할 수도 있겠지만, 어쨌든 rev.ng가 클라우드에서 실행될 때만 영향이 있음
      RPATH_PLACEHOLDERHARD_FLAGS_CXX_CLANG은 revng가 번역한 바이너리를 링크할 때 쓰이고, 종단 간 바이너리 번역에 관심 없다면 중요하지 않음
      우리는 의도적으로 DT_RUNPATH를 원함. DT_RPATH는 폐기 예정이고, LD_LIBRARY_PATH로 우리 라이브러리를 대체해야 하는 사용 사례가 있을 수도 있음
      “환경 조작”에 대한 지적은 비공개 환경 변수가 아닌 경우에만 타당하다고 봄
      RPATH_PLACEHOLDER, HARD_*, REVNG_*는 비공개 변수이고 전부 바이너리 번역 목적임
      더 작은 범위의 컴파일러 래퍼 안으로 밀어 넣을 수는 있지만, Python을 함께 배포하기 때문에 환경을 완전히 없앨 수는 없음
      Clang에 일부 플래그를 구워 넣는 것만으로는 안 됨. 이 플래그들은 링커에도 영향을 주고, 래퍼 기능 중 단순히 내장할 수 없는 것들이 있음
      다만 더 비공개인 위치로 옮길 수는 있음
      동적 링크를 경계하는 것 같은데, 우리는 여기에 노력을 들였고 이제 꽤 잘 동작하며 항상 올바른 위치를 찾음
      절대 경로를 하드코딩하지 않고, 바이너리를 “패치”하는 설치 단계도 없음. 압축을 푼 디렉터리는 어디로든 옮길 수 있음
      우리가 쓰는 해법은 LD_LIBRARY_PATH를 쓰지 않고, 모든 바이너리가 $ORIGIN을 통해 견고하게 서로를 참조함
      ./root/bin/python ./root/bin/revng artifact --help를 실행해보면 동작함
      다시 말하지만 source environment는 거의 데모용이고, 실제 사용에서는 ./revng만 실행하면 환경은 그대로임
      Python도 함께 배포하지만 꼭 그걸 쓸 필요는 없음. ./revng를 쓰거나 데몬 모드에서 네트워크로 상호작용하면 됨
      접근 방식은 원하는 스크립팅 도구로 YAML 프로젝트 파일을 파싱하고 수정한 뒤 ./revng artifact를 호출하거나 데몬과 상호작용하는 것임: https://docs.rev.ng/user-manual/model-tutorial/
      결과적으로 우리는 최신 Python 버전을 쓰고, 사용자는 원하는 언어를 쓸 수 있음
      이후에는 다양한 Python 버전과 호환되는 보조 래퍼를 PyPI에 제공할 예정임
      요약하면 source ./environment를 하지 말고 ./revng를 쓰면 됨
      이런 부분에 신경 쓰는 사람이 있어서 기쁨
      다음 큰 반복에서는 nix + mount namespace를 도입해 루트 권한 없이 /nix/store를 사용할 수 있게 하면서 많은 것을 단순화할 수도 있음
      이런 논의는 여기보다 Discord 서버에서 이야기하는 편이 나을지도 모름
  • 축하함
    QEMU TCG에 리프팅을 맡긴 것에 대해 후회가 있나, 아니면 잘 동작했나?

    • 아주 잘 동작했음. 후회는 두 가지임
      첫째, QEMU 포크를 몇 년 동안 리베이스하지 않아 안 좋은 상황이 됐음
      그래도 바로 오늘 팀원이 최신 QEMU로 리프팅에 성공했고, 우리가 QEMU에 지원 추가를 도운 Qualcomm Hexagon 코드도 리프팅할 수 있었음
      결국 우리는 최초의 제대로 된 Hexagon 디컴파일러가 될 것임
      둘째, QEMU에 너무 집중한 탓에 프런트엔드가 QEMU와 강하게 결합됨
      이제 QEMU 기반이 아닌 추가 프런트엔드를 지원하려면 노력이 좀 필요하지만 불가능하지는 않음
      구상은 사용자가 새 아키텍처 지원을 추가할 때 C로 CPU 상태 구조체와 그 위에서 동작하는 함수 몇 개만 정의하게 하는 것임
      내부 표현을 배울 필요가 없음
      요약하면 QEMU는 훌륭한 선택이었고, 너무 잘 동작해서 그 코드베이스 부분을 오래 건드리지 않다 보니 기술 부채가 생겼지만 지금 해결 중임