Skip to content

Commit

Permalink
Add section 3.4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Chi-En Wu committed May 2, 2017
1 parent 623b727 commit f2d24b4
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 0 deletions.
1 change: 1 addition & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* [3.3.4. 多處理器支援](cpu-caches/cpu-cache-implementation-details/multi-processor-support.md)
* [3.3.5. 其它細節](cpu-caches/cpu-cache-implementation-details/other-details.md)
* [3.4. 指令快取](cpu-caches/instruction-cache.md)
* [3.4.1. 自我修改的程式碼](cpu-caches/instruction-cache/self-modifying-code.md)
* [6. 程式設計師能做些什麼?](what-programmers-can-do.md)
* [6.1. 繞過快取](what-programmers-can-do/bypassing-the-cache.md)

13 changes: 13 additions & 0 deletions cpu-caches/instruction-cache/self-modifying-code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 3.4.1. 自我修改的程式碼

在電腦時代的早期,記憶體是很珍貴的。人們不遺餘力地減少程式的大小,以為程式資料騰出更多的空間。一個經常使用的技巧是,隨著時間改變程式自身。偶爾仍舊會找到這種自我修改的程式碼(Self Modifying Code,SMC),如今多半是為了效能因素、或者用在安全漏洞上。

一般來說應該避免 SMC。雖然它通常都被正確地執行,但有著並非如此的邊界案例(boundary case),而且沒有正確完成的話,它會產生效能問題。顯然地,被改變的程式碼無法維持在保存被解碼指令的追蹤快取中。但即使程式碼完全(或者有時候)不會被執行,因而不會使用到追蹤快取,處理器也可能會有問題。若是接下來的指令在它已經進入管線的期間被改變了,處理器就得丟掉大量的成果,然後從頭開始。甚至有處理器的大多狀態都必須被丟棄的情況。

最後,由於處理器假定––為了簡化起見,而且因為這在 99.9999999% 的情況下都成立––程式碼分頁是不可修改的(immutable),所以 L1i 的實作不會採用 MESI 協定,而是一種簡化的 SI 協定。這表示,若是偵測到了修改,就必須做出許多的悲觀假設。

強烈地建議盡可能避免 SMC。記憶體不再是如此稀有的資源。最好是撰寫各自的函式,而非根據特定的需求修改一個函式。或許有天 SMC 的支援能夠是可選的,而我們就能夠以這種方式偵測出嘗試修改程式碼的漏洞程式碼(exploit code)。若是真的必須使用 SMC,寫入操作應該要繞過快取,以免因為 L1i 所需的 L1d 的資料造成問題。關於這些指令的更多訊息,見 6.1 節。

在 Linux 上,識別出包含 SMC 的程式通常非常容易。使用正規工具鏈(toolchain)建構的話,所有程式的程式碼都是防寫的(write-protected)。程式設計師必須在連結期(link time)施展強大的魔法,以產生程式分頁能夠被寫入的可執行檔。當這種情況發生時,現代的 Intel x86 與 x86-64 處理器具有專門的、計算自我修改的程式碼使用次數的效能計數器。
有了這些計數器的幫助,非常輕易就能夠識別有著 SMC 的程式,即使程式由於寬鬆的許可而成功執行。

0 comments on commit f2d24b4

Please sign in to comment.