在 x86 環境下編譯 GCC 4.8 會出現 '_ITM_TYPE_M256' does not name a type 的錯誤

我想應該不少人已經知道 x86 平台被很多 software developer 無視已久了。
特別是歷經了用 gcc -O3 編譯 zlib 以後會讓包括 ssh 在內的一大堆程式爆炸,叫修又被裝死很長一段時間的這段血淚史,讓我對這個潮流更加印象深刻:
Bug 270120 - (PR40838) [4.4/bad-code] -ftree-vectorize causes segfaults on x86 due to stack misalignment
Bug 41156 - [4.4/4.5/4.6 Regression] zlib segfault in inflate_table() compiled w/ -O -msse2 ftree-vectorize
不過最近在租用外國 KVM 服務的時候,居然遇到一家實體 CPU 採用 Xeon E3-1270 V2 的主機商,無論如何就是無法讓 64-bit 的 FreeBSD ISO 能 boot 起來,無論是 8.3 和 9.1 都不行。
相對地,其它 Linux 家族的 64-bit 安裝光碟都完全沒事,可以正常 boot 也能裝得很開心,這實在是讓我這個喊了 FreeBSD 才是王道超過 10 年的人看得很傻眼。
雖然主機商馬上 call 了 FreeBSD 的 maintainer 來看看有沒有辦法解決,但最後只是推測這新的 CPU 架構和 USB 裝置的初始化有衝突,要修正還是不知道得等到何年何月,所以我就和主機商說讓我改裝 i386 的 FreeBSD 9.1 了。
因此在切換到 x86-64 環境的數年後,我又再次被迫回到 x86 平台這個戰場來編譯程式,向者艱辛的道路邁進。

說起這家 VPS 主機商,他們態度很友善,技術底感覺也很厚,在 Linux 和 FreeBSD 社群似乎都相當容易找到人問問題,也願意幫我客製化 VPS。
雖說日本那邊流行 KVM VPS 已經有相當久的時間了,譬如「さくらインターネット」和「お名前.com」這兩家,技術成熟且有自己開發的面板,但在歐美當地 KVM 只是剛起步而已。
不同於日本喜歡自己設計前端面板,歐美大都是採用 QEMU + libvirt + SolusVM 的組合,因此一些比較彈性的部分會受到 SolusVM 面板的功能限制。
因此雖說日本那邊的 VPS 大都可以看見 CPU 實際的名稱,並且使用完整的 CPU 指令集,但歐美那邊還是在使用預設的高相容性模擬 CPU:

CPU: QEMU Virtual CPU version (cpu64-rhel6) (3967.16-MHz K8-class CPU)
Origin = "GenuineIntel" Id = 0x6d3 Family = 6 Model = d Stepping = 3
Features=0x178bfbfd
Features2=0x80002001
AMD Features=0x20100800
AMD Features2=0x1

由於 SolusVM 並不提供指定 CPU mode 的功能,想在歐美主機商那邊要求能用到全部指令集的話,大都要請他們在 SolusVM 的 live config 裡把 <cpu> 改成 <cpu mode="host-passthrough">,而且不是每個主機商都知道 SolusVM 應該要在這邊修改不會一直被還原。
這家主機商很樂意幫我做這個設定,而且也相當積極在協助各種除錯和嘗試,所以我也懶得去試別家了。

廢話了兩段,來回到正題吧,首先要說明如何觸發這個錯誤。
方法很簡單,在 /etc/make.conf 放個 CFLAGS+="-O3 -march=native -mno-avx" 再去裝 ports 裡的 lang/gcc48,你就會遇到了。
雖說在 Core 2 系列剛出來的那幾年,i386 平台的安全 CFLAG 是 -march=prescott,否則產生 illegal instruction 的機會是相當大的,但近幾年 -march=corei7 已經相當安全。
不過安全歸安全,但如果是 -march=corei7-avx 的話,還是得另外擺上 -mno-avx,否則還是會看見 illegal instruction 的生成,其中最眾所皆知的就是 LDS 指令。
總之一旦使用了上面說到的 CFLAG,你在編譯到 libitm 的地方時,就會遇到標題上那個錯誤訊息。
這問題的解決方法其實早在去年就有人討論了:Bug 53113 - Build fails in x86_avx.cc if AVX disabled but supported by as (Solaris & Linux)
目前這個 bug 也一直還在 UNCONFIRMED 的狀態,丟 patch 的人也不知道這樣改會不會造成問題,反正能編過就好了?
總之那邊就是在裝死,和之前 zlib 慘死事件一樣裝死,所以就先隨便啦,我現在也沒空去看。
反正這 VPS 不是拿來幹什麼正經事,所以基本上是沒有什麼差。