2015-01-06 17 views
7

Tôi có một lĩnh vực quy định tại CIL như thế này:loại khác nhau có cùng một chữ ký trong CIL

.field public int32 modopt(void*) fld 

tôi biên dịch này cho một assembly. Bây giờ tôi thay đổi nó thành:

.field public int32 modopt(int16) fld 

Cả thế nào là nó có thể bây giờ, rằng các báo cáo ILDASM (khi hiển thị như hex) cả những lĩnh vực như thế này?

Field #1 (04000001) 
------------------------------------------------------- 
    Field Name: fld (04000001) 
    Flags  : [Public] (00000006) 
    CallCnvntn: [FIELD] 
    Field type: CMOD_OPT 1b000001 I4 
    Signature : 06 20 06 08 

Mã này tìm cả hai trường giống hệt nhau (thực tế tôi đã tạo trường thứ hai để khớp với chữ ký được báo cáo). Chữ ký rõ ràng khớp với trường thứ hai, nhưng chữ ký của trường đầu tiên sẽ trông giống như sau: 06 20 0f 01 08! Tôi đang thiếu gì ở đây?

Edit:

C# không thể phát ra loại lĩnh vực, ném một ngoại lệ về con trỏ và mảng loại không được hỗ trợ cho loại hình tùy chỉnh bổ, vì vậy đây rõ ràng giải quyết phù hợp chữ ký. Nhưng câu hỏi tại sao ILDASM cho phép tạo ra một chữ ký không hợp lệ mà nó không thể dịch ngược lại.

Chỉnh sửa # 2:

Dường ILASM thực sự tạo ra đúng IL, có một sự khác biệt trong các bãi chứa hex tôi đã bỏ lỡ lần cuối:

//the first assembly 
TypeSpeC#1 (1b000001) 
------------------------------------------------------- 
    TypeSpec : Ptr Void 
    Signature: 0f 01 

//the second assembly 
TypeSpeC#1 (1b000001) 
------------------------------------------------------- 
    TypeSpec : I2 
    Signature: 06 

Vì vậy, đó chỉ là một lỗi trong ILDASM hex dump báo cáo chữ ký thành viên sai (mặc dù tôi tự hỏi, nơi 06 trong chữ ký sai đến từ).

+0

Để đặt câu hỏi rõ ràng: điều gì khiến bạn nghĩ rằng đó là '06 20 0f 01 08'? Có sự cố/tham chiếu đến điều đó không? –

+0

@Marc Tôi đã xem ECMA của CLI. Kiểu phần tử của modopt là '20', kiểu phần tử của con trỏ là' 0f', của void là '01'. Vì vậy, việc kết hợp tất cả chúng lại với nhau, chữ ký của 'modopt (void *)' phải là '20 0f 01' (' 06' là trường callconv và '08' là int32). – IllidanS4

+0

là C# này? Tôi thấy mất hiệu lực *! – niceman

Trả lời

1

Hãy cố gắng tạo chữ ký trường theo cách thủ công dựa trên the specification. Để bắt đầu, ký hiệu trường được định nghĩa trong §II.23.2.4. Đối với trường hợp của chúng tôi với sửa đổi một tùy chỉnh, nó sẽ là:

FIELD CustomMod Type 

Kể từ FIELD được định nghĩa là 0x06, ta có:

06 CustomMod Type 

sửa đổi tùy chỉnh của chúng tôi là modopt, vì vậy chúng tôi có được (dựa trên §II .23.2.7):

06 CMOD_OPT TypeDefOrRefOrSpecEncoded Type 

CMOD_OPT là 0x20 (§II.23.1.16):

06 20 TypeDefOrRefOrSpecEncoded Type 

Chúng tôi muốn tham chiếu TypeSpec 0x1b000001, được mã hóa là 0b110 (10 cho TypeSpec, 1 cho 0x000001, §II.23.2.8). Đây là sau đó "nén" vào đơn byte 0x06 (§II.23.2):

06 20 06 Type 

Cuối cùng, loại là int32, đó là ELEMENT_TYPE_I4 = 0x08 (§II.23.2.12 và §II.23.1. 16):

06 20 06 08 

Vì vậy, chúng tôi có được chính xác chữ ký giống như chữ được hiển thị trong ILDasm.

+0

Cảm ơn, điều này có ý nghĩa hơn nhiều. Tôi nghĩ rằng nó được cho là kiểu chữ ký, không phải loại mã thông báo, vì vậy tôi đã hiểu sai kết quả của ILDasm. – IllidanS4

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