2009-05-31 25 views
6

Điều này nghe có vẻ như một câu hỏi đầu tiên, nhưng chịu với tôi.Phần nào (cụ thể) của một tệp thực thi tự nhiên làm cho nó không thể di chuyển được?

Kiến thức chung là các tệp nhị phân cho một cấu trúc CPU không chạy trên các cấu trúc khác. Vì vậy, ví dụ nó không thể chạy (không có một lớp tương thích của một số loại), một x86 nhị phân trên một chip sparc64. Các bộ hướng dẫn khác nhau, vì vậy rõ ràng rằng sẽ không hoạt động.

Nhưng khi nhị phân là cho cùng một CPU, nhưng đối với một hệ điều hành khác, phần nào của mã này ngăn không cho thực thi được. Ví dụ, chạy một x86 Solaris nhị phân trên một hộp Linux x86. Tôi giả định rằng có một số loại nền tảng cụ thể mà liên quan đến thời gian chạy linker hoặc quá trình lên lịch?

Tôi muốn biết. Cảm ơn.

Trả lời

12

Có một số lý do. Những cái chính, được đặt hàng trong "khoảng cách từ kim loại" là:

  1. Hệ điều hành có thể có các định dạng nhị phân khác nhau cho các tệp thi hành. Trong trường hợp này, bạn sẽ không thể tải nhị phân ngay từ đầu.
  2. Chương trình có thể sử dụng một phương pháp khác để cho biết họ muốn thực hiện cuộc gọi hệ thống (ví dụ: INT21 và INT80).
  3. Chương trình có thể dựa vào các cuộc gọi hệ thống không có trong hệ điều hành khác (ví dụ: dlopen())
  4. Chương trình có thể dựa vào thư viện chuẩn không có trên hệ điều hành khác.
  5. Chương trình có thể dựa vào các thư viện khác không có sẵn trên hệ điều hành khác.

Tất nhiên, có nhiều cách khác để chương trình chạy trong môi trường không mong muốn có thể thất bại một cách ngoạn mục.

+1

Lý do 1, 2 và 3 rất dễ sửa. Linux đã hỗ trợ một số lượng lớn các định dạng thực thi. Các ngắt mới có thể được tạo ra với một mô-đun hạt nhân có thể nạp được. Và các cuộc gọi hệ thống thường tương ứng khá tốt giữa các hệ điều hành khác nhau. – Zifre

+0

Tôi nên nói rằng chúng tôi đang giả định ELF :) Cảm ơn câu trả lời. –

1

Đó là các thư viện hệ thống cụ thể không phải lúc nào cũng di động. Ví dụ, bạn không thể sử dụng win32 window api trên vanilla linux (và có tôi nhận ra có arrounds làm việc cho điều này như rượu vang, nó không phải là ví dụ tốt nhất).

3

Chủ yếu là các API. Ví dụ, các API Win32 không thực sự có sẵn trên Linux. Mặc dù vậy, bạn có thể thực hiện việc này, xem Wine. Định dạng thực thi cũng có thể khác (ELF/PE), nhưng có thể được sửa lại khá dễ dàng (Wine thực hiện điều này; nó cho phép thực thi PE trên Linux).

Ngoài ra, ví dụ về thực thi Solaris và Linux của bạn sẽ khá dễ thực hiện, vì hệ điều hành rất giống nhau (ELF cho định dạng thực thi, API POSIX, hệ thống cửa sổ X, v.v.). FreeBSD có thể chạy các tệp thi hành Linux. Lý do điều này không quá phổ biến chỉ đơn giản là không có nhiều nhu cầu về nó. Có rất nhiều chương trình Windows nhiều hơn * NIX chương trình, do đó, Wine đã được tạo ra. Có rất nhiều chương trình Linux hơn các chương trình FreeBSD, vì vậy FreeBSD đã triển khai lớp tương thích với Linux. Solaris cuối cùng có thể thực hiện một cái gì đó tương tự quá. Tuy nhiên, đừng mong đợi sự đảo ngược (Solaris/BSD thực thi trên Linux), vì không có nhu cầu cho nó.

1

Thư viện và API hệ thống. Mã đơn giản thực sự sẽ hoạt động. Đây là lý do tại sao các lớp như Wine không thực hiện bất kỳ mô phỏng CPU nào, chúng chỉ tái triển khai API Windows.

0

Như đã được chỉ ra, tính không tương thích có ít liên quan đến các định dạng có thể thực thi hơn, sau đó các thư viện được tham chiếu bởi một tệp thực thi.

Tôi tin rằng linux thực sự tương thích với một số định dạng thực thi khác nhau mặc dù tôi có thể sai ở đây

5

Có bốn vấn đề:

  1. hệ điều hành khác nhau gói thực thi nhị phân của họ khác nhau (ví dụ như Linux ELF vs định dạng Windows);
  2. Các bộ lệnh khác nhau trên các kiến ​​trúc CPU khác nhau;
  3. Các hệ điều hành khác nhau có các cuộc gọi hệ thống khác nhau (ví dụ: CreateProcess() trong Win32 vs fork() trong Linux/Unix);
  4. Sự khác biệt như đường dẫn, ký tự pháp lý, dấu tách thư mục, v.v.

Thư viện không thuộc hệ thống được giả định là có mặt trên cả hai, nếu không thì đó là một sự khác biệt.

1

Ngoài những gì người khác đã nói, định dạng thực tế của tệp thực thi có thể khác nhau. Vì vậy, khi hệ điều hành đến để tải nó, nó không tìm thấy các giá trị mà nó mong đợi cho mã, phân đoạn dữ liệu, vv ở đúng nơi trong tệp.

+1

Một lần nữa, điều đó có thể được sửa chữa khá dễ dàng. Linux đã hỗ trợ nhiều định dạng thực thi. Rượu cũng vậy. Các thư viện là một * nhiều * yếu tố lớn hơn so với định dạng thực thi. – Zifre

2

Bên cạnh định dạng nhị phân và các tính năng "đóng gói" khác (có thể không chính xác tầm thường) Hoặc cũng có những hậu quả mà bạn tìm thấy trong hầu hết các đoạn mã. Các nội dung như

  1. PIC có thể khiến mọi truy cập toàn cầu dựa vào giả định cụ thể của hệ thống khi tải lại con trỏ GOT và giả định về bù trừ bổ sung.
  2. Nhiều hệ thống có ABI cụ thể, qua các thanh nhỏ trong sổ đăng ký, bỏ qua thanh ghi cho mục đích liên kết, đặt trước thanh ghi cho các mục đích đặc biệt Một số có một số (như ARM EABI và OABI)
  3. mỗi sợi được gắn chặt với các cơ sở mà hệ điều hành chỉ định. Đăng ký lựa chọn, bù trừ, vv
  4. Một số hệ điều hành (đáng chú ý nhất) cửa sổ có hỗ trợ cho một định dạng xử lý ngoại lệ nhất định để cho phép xử lý ngoại lệ chéo và thậm chí qua máy (qua DCOM).
  5. Hệ thống chương trình đa cấp cao hơn (như COM, nhưng cũng như khả năng tương tác mục tiêu C trên máy Mac hoặc khả năng tương thích với phiên bản KDE-gcc) cũng có các yêu cầu nhất định về bố cục VMT.
  6. Một số liên kết và định dạng hỗ trợ phần bù âm với một phần, một số thì không.

Lưu ý rằng đây chỉ là một điều thú vị mà bạn có thể quan tâm. Nó có lẽ không hoàn chỉnh, và không phải tất cả đều có thể áp dụng. Một số điểm trên có thể trùng lặp (ví dụ: đặt trước thanh ghi cho TLS hoặc PIC cũng là thay đổi ABI)

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