我想在我的程序中生成一些機器代碼,然後運行它。一種方法是編寫一個.so文件,然後將其加載到程序中,但似乎太昂貴。在NX位分配關閉在Linux中的數據頁
有沒有辦法在linux中爲我寫出我的數據頁面中的代碼,然後設置我的函數ointer在那裏,只是調用它?我在窗口上看到了類似的東西,您可以在該頁面關閉NX保護的情況下分配頁面,但我找不到類似的Linux操作系統調用。
我想在我的程序中生成一些機器代碼,然後運行它。一種方法是編寫一個.so文件,然後將其加載到程序中,但似乎太昂貴。在NX位分配關閉在Linux中的數據頁
有沒有辦法在linux中爲我寫出我的數據頁面中的代碼,然後設置我的函數ointer在那裏,只是調用它?我在窗口上看到了類似的東西,您可以在該頁面關閉NX保護的情況下分配頁面,但我找不到類似的Linux操作系統調用。
該mmap(2)(與munmap(2)
)和mprotect(2)系統調用是這樣做的基本操作。回想一下,從應用程序的角度來看,syscalls是基本操作。你想要PROT_EXEC
你可能只是strace
任何動態鏈接的可執行文件,以獲得有關如何調用它們的線索,因爲動態鏈接程序ld.so
正在使用它們。
生成共享對象可能比您想象的要便宜。實際上,生成C代碼,運行編譯器,然後生成共享對象也是有意義的,即使在交互式工作時也是如此。我的MELT域特定語言(擴展GCC)正在這樣做。回想一下,你可以做很多dlopen
-s沒有問題。
如果你想在內存中生成的機器代碼,你可以使用GNU lightning(快速生成慢的機器代碼),libjit
從dotgnu(產生更少的壞機器代碼),LuaJit,asmjit(x86或AMD64具體),LLVM(慢慢生成優化的機器碼)。順便說一下,SBCL Common Lisp實現動態編譯到內存,並在運行時產生良好的機器代碼(並且JVM也是所有的JIT)。
非常感謝您的回答。在現代硬件上(2GHz Core i7,72RPM磁盤,DDR4),你認爲需要多長時間寫出5MB的代碼並通過dlopen加載它?如果可能的話,我希望它在100ms以下,這樣它不會爲我的處理增加太多的開銷。 –
我不知道,它確實取決於代碼;你可以測量它。大部分時間將用於構建機器碼。順便說一句,5MB的代碼是相當多的。在我的Debian/Sid/AMD64上,我在/ usr/bin中有3920個文件,但只有30個大於5MB。如果你需要發出這麼多的代碼是很少的時間,你可能會被限制爲GNU閃電(但生成的代碼非常慢)。你確定你的5MB二進制代碼閾值在100ms內是否真實?對我來說這似乎很重要。 –
另外,5MB/100ms意味着在兩分鐘內您的進程地址空間增長了6Gb。 (一小時內180Gb),我認爲這可能不合理。您的5MB希望在0.1秒內似乎不合理(並且很難在很短的時間內生成足夠好的機器碼 - 這種大小的寄存器分配和指令調度的考慮)。 –
請參閱:http://stackoverflow.com/questions/3125756/allocate-executable-ram-in-c-on-linux,特別是來自Ulrich Drepper的鏈接文章。 – ninjalj