2012-01-11 32 views
7

Tôi đang cố gắng hiểu cách thức các tệp Mach-o hoạt động và đã có tiến bộ tốt với các tài nguyên trực tuyến sẵn có (Cụ thể, trang Apple tại đây: http://developer.apple.com/library/mac/#documentation/developertools/conceptual/MachORuntime/Reference/reference.html), nhưng tôi đã đánh một rào cản về sự hiểu biết cách biểu tượng làm việc.Sơ đồ biểu tượng Mach-O (IOS)

Sử dụng "otool -l" Tôi thấy phần sau:

Section 
    sectname __symbolstub1 
    segname __TEXT 
     addr 0x00005fc0 
     size 0x00000040 
    offset 20416 
    align 2^2 (4) 
    reloff 0 
    nreloc 0 
    flags 0x80000408 

Tuy nhiên khi tôi nhìn vào các dữ liệu từ các tập tin nhị phân trong một trình soạn thảo hex tôi thấy 4 byte sau lặp đi lặp lại một lần nữa và một lần nữa:

00005FC0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 
00005FD0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 
00005FE0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 
00005FF0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 

Điều này trông giống như LDR làm tăng máy tính theo số tiền cố định, nhưng tôi không thấy lý do số tiền này giống nhau cho mỗi mục nhập trong bảng biểu tượng.

Nếu ai đó có thể làm sáng tỏ lý do tại sao điều này xảy ra hoặc cung cấp bất kỳ tài nguyên nào có mức thấp này, vui lòng cho tôi biết.

Cảm ơn!

+0

Tôi nghĩ rằng tôi đã tìm ra những gì đang diễn ra, mỗi mục trong 4 byte trong bảng sẽ trỏ đến vùng dữ liệu bên dưới có lệnh DCD lưu trữ vị trí của cuộc gọi hàm. Tuy nhiên tôi vẫn còn một chút nhầm lẫn lý do tại sao mức độ thêm này của indirection là cần thiết, vì vậy nếu có ai có thể cung cấp thông tin theo tôi sẽ đánh giá cao nó. – Locksleyu

Trả lời

12

Tôi sẽ mô tả tình huống với iOS hiện tại, nó hơi khác trong các phiên bản cũ.

Cuống biểu tượng thực sự tải vào PC một con trỏ hàm. Đối với tiêu chuẩn "lười biếng" (on-demand) nhập khẩu, con trỏ nằm trong phần __lazy_symbol và bước đầu chỉ ra một thói quen helper trong phần __stub_helper, ví dụ:

__symbolstub1 _AudioServicesAddSystemSoundCompletion 
__symbolstub1 LDR PC, _AudioServicesAddSystemSoundCompletion$lazy_ptr 
__symbolstub1 ; End of function _AudioServicesAddSystemSoundCompletion 

__lazy_symbol _AudioServicesAddSystemSoundCompletion$lazy_ptr DCD _AudioServicesAddSystemSoundCompletion$stubHelper 

__stub_helper _AudioServicesAddSystemSoundCompletion$stubHelper 
__stub_helper LDR R12, =nnn ; symbol info offset in the lazy bind table 
__stub_helper B dyld_stub_binding_helper 

Chức năng dyld_stub_binding_helper là nắm tay một trong __stub_helper phần và về cơ bản chỉ là một tấm bạt lò xo để các chức năng dyld_stub_binder trong dyld, đi qua với nó những gì tôi gọi là "biểu tượng thông tin bù đắp" giá trị. Giá trị đó là một bù đắp bên trong luồng thông tin ràng buộc lười biếng (được chỉ ra bởi lệnh tải LC_DYLD_INFO hoặc LC_DYLD_INFO_ONLY), đây là một loại luồng bytecode với các lệnh cho dyld. chuỗi điển hình cho một khẩu lười biếng trông như thế này:

72: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(M, 0xYYYYY) 
19: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(NNNN) 
40: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x00, '_AudioServicesAddSystemSoundCompletion') 
90: BIND_OPCODE_DO_BIND() 

đây dyld sẽ làm như sau:

  1. nhìn lên hàm có tên '_AudioServicesAddSystemSoundCompletion' từ một số dylib NNNN trong danh sách các dylibs liệt kê trong tải các lệnh .
  2. tra cứu số phân đoạn có thể thực thi M (rất có thể là __DATA)
  3. viết con trỏ hàm tại YYYYY offset.
  4. nhảy đến địa chỉ ngẩng đầu lên để các chức năng thực hiện công việc của mình

Địa chỉ ghi vào sẽ xảy ra là khe _AudioServicesAddSystemSoundCompletion$lazy_ptr. Vì vậy, lần sau, _AudioServicesAddSystemSoundCompletion được gọi, nó sẽ nhảy trực tiếp đến chức năng được nhập, mà không phải qua dyld.

N.B.: bạn không nên nhìn vào offset 05fc0 trong tệp ngay lập tức. Trường addr là địa chỉ ảo, bạn nên tra cứu lệnh chứa phân đoạn và xem VA bắt đầu từ gì và bù đắp tệp của nó là gì, sau đó thực hiện phép toán. Thông thường, phân đoạn __TEXT bắt đầu ở 1000.

Tuy nhiên, các ký hiệu thực tế biểu tượng trông giống như bạn dán, có thể bạn có một chất béo mach-o với tiêu đề chất béo lấy 1000 byte đầu tiên, do đó, bù đắp xếp hàng.

+0

+1. Chậm vỗ, đứng lên hoan nghênh. Câu trả lời tuyệt vời. Tôi đã học được rất nhiều từ đó! – mattjgalloway

+0

Wow, câu trả lời tuyệt vời! Tôi phải đọc nó một vài lần trước khi tôi hoàn toàn có thể hiểu được, nhưng Igor hãy nói với tôi một điều. Bạn lấy kiến ​​thức này ở đâu? Bằng cách đọc tất cả các ASM có liên quan hoặc là tài liệu này hoàn toàn bất cứ nơi nào? Cảm ơn! – Locksleyu

+0

Chủ yếu là từ các tệp nhị phân, có. Tuy nhiên, về lý thuyết bạn cũng có thể tìm ra từ mã nguồn - xem [nguồn của Apple] (http://opensource.apple.com/source/) cho dyld, ld64 và Csu. –

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