LD_PRELOAD對PHP extension失效的原因

最近寫了一個主機健康檢測和軟負載均衡用的軟件ZFOR(http://github.com/chaoslawful/zfor ),可以通過LD_PRELOAD預載入的方式攔截系統的域名解析調用(gethostbyname、getaddrinfo等)。但發現對某些發行版的PHP CURL extension光加載zfor動態庫沒有用,還必須同時加載libcurl.so才能生效。

 

經過一番搜索,發現原來是PHP編譯時讓Zend引擎使用了RTLD_DEEPBIND標誌來加載擴展,該標誌的作用是約束動態符號解析的查找範圍爲載入的動態庫及其依賴項,而不是從所有已加載項的符號表中尋找。PHP啓用該選項的原意是避免同時加載多個具有共同依賴庫的擴展時產生多版本符號解析衝突的問題,但在這裏就影響了zfor的preload攔截過程。因爲PHP CURL擴展只依賴libcurl.so而不依賴libzfor.so,故在不預加載libcurl.so時libzfor.so不會列入PHP CURL擴展符號解析的查找範圍,這樣在libzfor.so中定義的getaddrinfo別名自然無法生效。

 

在同時預加載libcurl.so和libzfor.so時,由於是系統的動態庫加載器ld-linux.so按默認解析策略進行符號解析,故會將libcurl.so中引用的getaddrinfo符號解析到libzfor.so中提供的實現上,而由於動態庫都是單實例加載的,這樣當PHP CURL擴展被載入時,其依賴的libcurl.so就會用之前預加載的那個實例來解決,不需要再進行符號查找,也就不用受到RTLD_DEEPBIND標誌的約束了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章