2010-05-18 30 views
14

Tôi đã biết về hướng dẫn jmp trong một thời gian, nhưng nó không bao giờ đánh tôi như là thậm chí từ xa không an toàn. Gần đây tôi đã có nguyên nhân để kiểm tra thông số kỹ thuật CIL và was very surprised to discover jmp is considered unverifiable.Tại sao lệnh jmp của CLR không thể xác minh?

+0

Điều này có thể bởi vì nó không thể xác minh tác động của thực hiện các phần khối mã hiện sau đó và khâu chặt vào khối mã điểm đến ... Something về ngăn xếp/theo dõi đống dường như cờ trong dreamworld nhỏ của tôi .. không phải là tôi biết điều này chắc chắn mặc dù ... tuy nhiên đó là ngay lập tức bù đắp bởi các thông tin ở đây ... http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.jmp .aspx ... trong đó nêu rõ rằng không có thông tin ngăn xếp nào được theo dõi/chuyển. Có thể có thứ gì đó bên dưới "giao diện người dùng" ở đây mà Microsoft đang ẩn. – War

+0

Tôi không biết tại sao nó không thể xác minh được nhưng tôi có một thông tin thú vị. EQATEC Profiler của chúng tôi thu thập số liệu thống kê ẩn danh về tất cả các mã mà nó cấu hình (sử dụng EQATEC Analytics, btw). Bởi vì jmp phức tạp và không được xử lý tối ưu bởi profiler, chúng tôi quyết định theo dõi tần suất nó thực sự xảy ra. Chúng tôi hiện có 2 năm dữ liệu, thu thập từ hơn 1 triệu hội đồng định hình, tổng cộng 20 tỷ chỉ dẫn CIL. Khá nhiều. Và bao nhiêu là jmp? Không ai! Có, một jmp chưa bao giờ xảy ra trong bất kỳ ứng dụng của người dùng của chúng tôi (NETCF, SL, WP7, F # vv). Khá bất ngờ. –

+1

Tôi không quá ngạc nhiên. Không có trình biên dịch tôi biết ngoại trừ có lẽ quản lý C + + phát ra lệnh jmp, bởi vì nó không thể xác minh. Bất kỳ việc sử dụng jmp nào cũng có thể được gửi đi trong các thư viện lớp đáng tin cậy. – naasking

Trả lời

4

Bởi vì, không giống như một call, callvirt, hoặc calli, nơi stack frame của người gọi sẽ vẫn còn trên ngăn xếp để được nhìn thấy bởi stackwalks an ninh truy xuất mã lệnh tương lai kích hoạt (có lẽ gián tiếp) bởi callee, một hướng dẫn jmp nước mắt xuống người gọi stack frame trước khi chuyển vào callee và do đó vô hình đối với bất kỳ stackwalks CAS nào mà callee có thể kích hoạt.

Chỉnh sửa: Tôi nghĩ naasking là đúng về câu trả lời ở trên là sai. Tôi bây giờ nghĩ rằng sự khác biệt giữa (có thể xác minh) đuôi.call trình tự và (unverifiable) jmp trình tự có thể là một cuộc gọi đuôi yêu cầu đẩy các đối số cho cuộc gọi vào ngăn xếp đánh giá, nơi họ có thể được xác minh theo cách bình thường, trong khi jmp yêu cầu ngăn xếp đánh giá trống và khiến cho jump-ee kế thừa các đối số của bước nhảy. Có lẽ không có lý do gì để làm phức tạp người xác minh kiểm tra các hướng dẫn jmp nhưng có thể làm như vậy trong các điều kiện tương tự với các yêu cầu trên các chuỗi tail.call (một trong số đó là người gọi và callee phải ở trong cùng một assembly). ra khỏi CAS của tôi đoán ở trên, ít nhất là lên đến rõ ràng .Deny() cuộc gọi).

Nếu vậy, đây sẽ là một phần liên quan của spec: (phân vùng III, Mục 3,37)

Những lập luận hiện đang chuyển với phương pháp đích.

Ngăn xếp đánh giá phải trống khi lệnh này được thực thi. Công ước gọi, số và loại đối số tại địa chỉ đích phải khớp với quy tắc hiện tại.

+0

Trong khi hợp lý lúc đầu đỏ mặt, điều này không đứng lên để giám sát kỹ hơn. Các .tailcall tiền tố có hành vi gần giống nhau, mặc dù tổng quát hơn, nhưng .tailcall là kiểm chứng. Tài liệu chỉ đơn giản tuyên bố rằng .tailcall được bỏ qua khi gọi từ mã không đáng tin cậy đến đáng tin cậy. Nếu đây là lý do jmp là unverifiable, tôi không thấy lý do tại sao họ sẽ không chỉ sử dụng cùng một hành vi cho jmp. – naasking

+0

Điểm rất tốt, cảm ơn naasking. –

+0

Tôi nghĩ "Rodrigo Kumpera" đã đăng trên trang blog được liên kết có quyền: nếu có đối số là by-ref, thì bạn có thể lưu trữ tham chiếu đến một địa phương rồi thực hiện một jmp. Một phân tích dòng chảy kiểm soát được yêu cầu để đảm bảo điều này không xảy ra, mặc dù một tương đối đơn giản. Tôi muốn đặt cược họ chỉ không muốn bận tâm kể từ khi jmp được thêm chủ yếu để hỗ trợ C + +. Mối nguy hiểm tương tự tồn tại đối với .tailcall, vì vậy tôi không chắc chắn cách xử lý đó, nghĩa là. không thể xác minh hoặc .tailcall bị bỏ qua. Tôi sẽ phải kiểm tra nó tại một số điểm. – naasking

Các vấn đề liên quan