2016-04-22 13 views
7

Trong khi giải quyết một lỗi tôi đã thấy một sự khác biệt giữa các bảng nhảy nhập khẩu của hai Win64 DLL. Phiên bản 64bit của kernel32.dll sử dụng chỉ dẫn đồng bằng FF25jmp trong các bảng nhảy nhập của nó. Mặt khác, phiên bản 64bit của advapi32.dll sử dụng 48FF25 cho biết tiền tố REX.w=1 trước mã vạch jmp. Tuy nhiên, cả hai dường như có toán hạng 32 bit chỉ định một địa chỉ offset RIP +.Ý nghĩa của tiền tố REX.w trước khi AMD64 jmp (FF25)

Có bất kỳ ý nghĩa nào đối với tiền tố REX.w trên mã opcode cụ thể này không?

Tôi không thường xuyên làm việc với mã máy, vì vậy hãy tha thứ cho bất kỳ sai sót thực tế nào.

+0

Tôi nghĩ bạn sẽ tìm thấy tài liệu đó trong tài liệu của Intel. –

+2

Nó không được liệt kê trong sách hướng dẫn sử dụng và các bộ tháo rời mà tôi cũng không thể hiểu được. Tôi nghĩ 'rex.w' chỉ bị bỏ qua. – Jester

Trả lời

9

Tiền tố REX.W bị bỏ qua. Ở chế độ 64 bit, mã opcode FF /4 luôn có toán hạng 64 bit (JMP r/m64), do đó các tiền tố thay đổi kích thước toán hạng (REX.W, 66) không có hiệu lực.

Lý do tại sao tiền tố REX.W này hiện diện có thể phù hợp với quy tắc của hội nghị gọi điện thoại x64 của Microsoft về việc giải quyết. Lệnh nhập nhảy có hiệu quả là một hàm lệnh, và vì các ngoại lệ trên Windows là không đồng bộ, chúng có thể xảy ra bất cứ lúc nào, có thể có một ngoại lệ được tạo ra trong khi thực thi hàm này. Microsoft đặt một số restrictions on instructions used at the start and end of functions. Đặc biệt, hàm phải kết thúc bằng một phần kết thúc chỉ chứa một số hướng dẫn nhất định. Theo Kevin Frei's blog trên MSDN nếu hướng dẫn cuối cùng là một bước nhảy gián tiếp thì phải sử dụng tiền tố REX.W:

Một lưu ý khác: nếu jmp thức không phải là một jmp ip tương đối, nhưng một gián tiếp jmp, nó phải được bắt đầu bằng tiền tố REX, để chỉ ra cho hệ điều hành thư giãn thói quen mà nhảy được chuyển ra ngoài chức năng, nếu không, hệ điều hành giả định đó là một bước nhảy đến một vị trí khác trong cùng một hàm.

Các mâu thuẫn giữa việc sử dụng REX.W có thể đã xảy ra vì nguyên tắc này được mô tả ở trên là không hoàn toàn phù hợp với những gì tài liệu Microsoft chính thức đòi hỏi của một hướng dẫn JMP thức:

Chỉ có một tập hợp con của báo cáo jmp được cho phép trong epilog. Đây là độc quyền của lớp jmps với tham chiếu bộ nhớ ModRM nơi ModRM mod giá trị trường 00. Việc sử dụng jmps trong epilog với giá trị trường mod ModMM 01 hoặc 10 đều bị cấm.

Lưu ý rằng vì điều này sẽ loại trừ hướng dẫn JMP tương đối không sử dụng mã hóa ModR/M, loại JMP phổ biến nhất để kết thúc một hàm, vì vậy tôi tin rằng đó là tài liệu chính thức lỗi ở đây.

Lý do khác có thể cho sự không nhất quán là trình gỡ lỗi của Microsoft xử lý các bước nhảy nhập đặc biệt hoặc các bước nhảy không có tiền tố REX.W là lỗi và sẽ khiến chương trình bị chấm dứt trong trường hợp rất hiếm khi xảy ra trường hợp ngoại lệ xảy ra trong khi chúng đang được thực hiện.

+3

Đó là lý do chính xác. CoreClr có một bản sao của hệ điều hành Unwinder tại https: // github.com/dotnet/coreclr/blob/master/src/unwinder/amd64/unwinder_amd64.cpp nơi bạn có thể kiểm tra cách hoạt động của stack unwinder. Nó thực sự kiểm tra tiền tố REX giống như Kevin đã chỉ ra trên blog của anh ấy. –

+3

Điều này cũng được bán tài liệu trong tài liệu SDK cho hàm ['RtlVirtualUnwind'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms680617.aspx), cụ thể trong phần" Ghi chú " , trong đó nó đưa ra một danh sách đầy đủ các điểm đánh dấu epilogue trên x64 được nhận dạng bởi mã thư giãn. –

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