Làm thế nào bản thân trình liên kết / trình tải động có thể được liên kết động như được báo cáo bởi `file`?


12

Xem xét các phụ thuộc đối tượng được chia sẻ của /bin/bash, bao gồm /lib64/ld-linux-x86-64.so.2(trình liên kết / trình tải động):

ldd /bin/bash
    linux-vdso.so.1 (0x00007fffd0887000)
    libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f57a04e3000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f57a04de000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f57a031d000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f57a0652000)

Kiểm tra /lib64/ld-linux-x86-64.so.2cho thấy rằng đó là một liên kết tượng trưng đến /lib/x86_64-linux-gnu/ld-2.28.so:

ls -la /lib64/ld-linux-x86-64.so.2 
lrwxrwxrwx 1 root root 32 May  1 19:24 /lib64/ld-linux-x86-64.so.2 -> /lib/x86_64-linux-gnu/ld-2.28.so

Hơn nữa, filecác báo cáo /lib/x86_64-linux-gnu/ld-2.28.socho chính nó được liên kết động:

file -L /lib64/ld-linux-x86-64.so.2
/lib64/ld-linux-x86-64.so.2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

Tôi muốn biết:

  1. Làm thế nào bản thân trình liên kết / bộ nạp ( /lib64/ld-linux-x86-64.so.2) tự động có thể được liên kết động? Nó liên kết chính nó trong thời gian chạy?
  2. /lib/x86_64-linux-gnu/ld-2.28.sođược ghi lại để xử lý các nhị phân a.out ( man ld.so), nhưng /bin/bashELF có thực thi được không?

Chương trình ld.so xử lý các nhị phân a.out, một định dạng được sử dụng từ lâu; ld-linux.so * (/lib/ld-linux.so.1 cho libc5, /lib/ld-linux.so.2 cho glibc2) han‐ dles ELF, mà mọi người đã sử dụng trong nhiều năm nay.


Hạt nhân không quan tâm đến sự tinh tế phân loại tinh tế như vậy (và bạn cũng không nên ;-)). Hạt nhân chỉ tạo ra sự khác biệt giữa các ELF cần một thông dịch viên và những người không có. Và AFAIK, bạn không thể sử dụng một trình thông dịch mà chính nó cần.
mosvy

@StephenKitt mine đã không ( /lib/x86_64-linux-gnu/ld-2.28.so, debian 10 buster)
mosvy

@mosvy yeah, xin lỗi, tôi đã filenhầm lẫn giữa nhận xét sai lầm về cách định nghĩa nhị phân tĩnh và thực tế của ld-2.28.so... Sự khác biệt là PT_DYNAMIC.
Stephen Kitt

Câu trả lời:


17
  1. Vâng, nó liên kết chính nó khi nó khởi tạo. Về mặt kỹ thuật, trình liên kết động không cần độ phân giải và di chuyển đối tượng cho chính nó, vì nó đã được giải quyết hoàn toàn, nhưng nó xác định các ký hiệu và nó phải quan tâm đến các phần tử khi giải quyết nhị phân mà nó phiên dịch, và các ký hiệu đó được cập nhật để chỉ ra các triển khai của chúng trong các thư viện được tải. Đặc biệt, điều này ảnh hưởng malloc- trình liên kết có phiên bản tối thiểu tích hợp sẵn, với ký hiệu tương ứng, nhưng được thay thế bằng phiên bản của thư viện C một khi nó được tải và di chuyển (hoặc thậm chí bởi một phiên bản xen kẽ nếu có), một cách cẩn thận được thực hiện để đảm bảo điều này không xảy ra tại thời điểm nó có thể phá vỡ liên kết.

    Các chi tiết gory là trong rtld.c, trong dl_mainchức năng.

    Lưu ý tuy nhiên ld.sokhông có phụ thuộc bên ngoài. Bạn có thể thấy các biểu tượng liên quan đến nm -D; không ai trong số họ là không xác định.

  2. Trang chủ chỉ đề cập đến các mục trực tiếp bên dưới /lib, tức là /lib/ld.so (trình liên kết động libc 5, hỗ trợ a.out) và /lib*/ld-linux*.so*(trình liên kết động libc 6, hỗ trợ ELF). Trang này rất cụ thể, và ld.sokhông ld-2.28.so.

    Trình liên kết động được tìm thấy trên phần lớn các hệ thống hiện tại không bao gồm a.outhỗ trợ.

filelddbáo cáo những điều khác nhau cho trình liên kết động bởi vì chúng có các định nghĩa khác nhau về những gì tạo thành một nhị phân liên kết tĩnh. Đối với ldd, một nhị phân được liên kết tĩnh nếu nó không có DT_NEEDEDký hiệu, tức là không có ký hiệu không xác định. Đối với file, nhị phân ELF được liên kết tĩnh nếu nó không có PT_DYNAMICphần (điều này sẽ thay đổi trong bản phát hành filesau 5.37; hiện tại nó sử dụng sự hiện diện của một PT_INTERPphần làm chỉ báo của nhị phân được liên kết động, phù hợp với nhận xét trong mật mã).

Trình liên kết động thư viện GNU C không có bất kỳ DT_NEEDEDký hiệu nào , nhưng nó có một PT_DYNAMICphần (vì về mặt kỹ thuật nó là một thư viện dùng chung). Kết quả là, ldd(là trình liên kết động) chỉ ra rằng nó được liên kết tĩnh, nhưng filechỉ ra rằng nó được liên kết động. Nó không có một PT_INTERPphần, vì vậy bản phát hành tiếp theo filecũng sẽ chỉ ra rằng nó được liên kết tĩnh.

$ ldd /lib64/ld-linux-x86-64.so.2
        statically linked

$ file $(readlink /lib64/ld-linux-x86-64.so.2)
/lib/x86_64-linux-gnu/ld-2.28.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

(với file5,35)

$ file $(readlink /lib64/ld-linux-x86-64.so.2)
/lib/x86_64-linux-gnu/ld-2.28.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

(với phiên bản hiện đang được phát triển file).


Tại sao từ "phiên dịch" được sử dụng trong ngữ cảnh của liên kết động? Từ đó thường được sử dụng trong ngữ cảnh của các ngôn ngữ lập trình.
Shuzheng

Bạn có ý nghĩa gì bởi "trình liên kết động thư viện GNU C"? Bạn đang đề cập đến /lib*/ld-linux*.so*, hoặc một liên kết động thứ ba?
Shuzheng

Bạn có thể thấy lddbáo cáo trình liên kết động ở đâu được liên kết tĩnh? Bởi vì danh sách các phụ thuộc đối tượng được chia sẻ là trống rỗng?
Shuzheng

Các chương trình liên kết động cần một số công việc được thực hiện cho chúng trước khi chúng có thể được thực thi; công việc đó được thực hiện bởi trình liên kết động, cuối cùng đóng vai trò tương tự như trình thông dịch - nó diễn giải các bảng di dời, v.v. để tạo ra thứ gì đó mà máy tính có thể chạy.
Stephen Kitt

Khi tôi nói thư viện liên kết động GNU GNU C, tôi đang đề cập đến việc triển khai có trong thư viện GNU C, thường được vận chuyển dưới dạng /lib*/ld-linux*.so*. Tôi đã chỉ định nguồn gốc của trình liên kết động vì có các triển khai khác có sẵn cho Linux.
Stephen Kitt

0
  1. Tôi nghi ngờ filechương trình sai về trình liên kết / trình tải động được tự động liên kết. Các lddchương trình không đồng ý. Ít nhất là không phải trên hệ thống của tôi (Debian Stretch):

    ldd /lib/x86_64-linux-gnu/ld-2.24.so
        statically linked
    
  2. man ld.socũng đọc: "ld-linux.so * xử lý ELF" . Trên hệ thống của bạn (và cả của tôi nữa) cả hai đều là các liên kết tượng trưng cho cùng một nhị phân mà tôi suy luận là có thể xử lý cả ELF và định dạng a.out lỗi thời.


thông tin nào bạn thêm vào câu trả lời được chấp nhận?
phép lạ173

2
@ miracle173 câu trả lời này cũ hơn câu trả lời được chấp nhận ;-).
Stephen Kitt

bạn đúng rồi. Tôi đã bỏ lỡ điều này. Tôi nghĩ rằng câu hỏi và câu trả lời được chấp nhận là rất cũ và câu trả lời này đã được đăng trong những giờ qua. Tôi không thể hoàn tác downvote của mình cho đến khi ai đó sửa đổi bài đăng.
phép lạ173
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.