2012-03-22 31 views
34

Các LD manual không giải thích những gì các KEEP lệnh nào. Dưới đây là đoạn trích từ tập lệnh trình liên kết của bên thứ ba có tính năng KEEP. Lệnh KEEP làm gì trong ld?KEEP có ý nghĩa gì trong một tập lệnh liên kết?

SECTIONS 
{ 
    .text : 
    { 
     . = ALIGN(4); 
     _text = .; 
     PROVIDE(stext = .); 
     KEEP(*(.isr_vector)) 
     KEEP(*(.init)) 
     *(.text .text.*)   
     *(.rodata .rodata.*)   
     *(.gnu.linkonce.t.*) 
     *(.glue_7) 
     *(.glue_7t) 
     *(.gcc_except_table) 
     *(.gnu.linkonce.r.*) 
     . = ALIGN(4); 
     _etext = .; 
     _sidata = _etext; 
     PROVIDE(etext = .); 
      _fini = . ; 
       *(.fini) 

    } >flash 
+4

KEEP được ghi lại trong phiên bản [this] (https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep) của hướng dẫn sử dụng. – alexei

Trả lời

37

Afaik LD giữ biểu tượng trong phần ngay cả khi biểu tượng không được tham chiếu. (--các phần).

Thường được sử dụng cho các phần có ý nghĩa đặc biệt trong quy trình khởi động nhị phân, ít nhiều để đánh dấu gốc rễ của cây phụ thuộc.


(Đối với Sabuncu bên dưới)

phụ thuộc cây:

Nếu bạn loại bỏ mã không sử dụng, bạn phân tích mã và đánh dấu tất cả các mục có thể truy cập (mã + biến toàn cục + hằng số).

Vì vậy, bạn hãy chọn một phần, đánh dấu nó như là "sử dụng" và xem những gì phần nó tham chiếu khác, sau đó bạn đánh dấu những phần như "sử dụng", và kiểm tra những gì họ tham khảo, vv

Phần mà không phải là được đánh dấu "đã qua sử dụng" sau đó dự phòng và có thể bị loại bỏ.

Vì một phần có thể tham chiếu nhiều phần khác (ví dụ: một quy trình gọi ba phần khác nhau), nếu bạn vẽ kết quả, bạn sẽ có được một cây.

Roots:

Tuy nhiên Các nguyên tắc trên lá chúng tôi với một vấn đề: "đầu tiên" phần đó luôn được sử dụng là gì? Nút đầu tiên (gốc) của cây để nói? Đây là những gì "giữ()", nó nói với các mối liên kết mà phần (nếu có) là những cái đầu tiên để xem xét. Kết quả là những liên kết này luôn được liên kết.

Thông thường đây là các phần được gọi từ trình tải chương trình để thực hiện các tác vụ liên quan đến liên kết động (có thể là tùy chọn và phụ thuộc vào OS/fileformat) và điểm nhập của chương trình .

+1

+1 Cây phụ thuộc là gì? Tại sao nó quan trọng để đánh dấu nguồn gốc của nó? Cảm ơn. – Sabuncu

+0

Tôi thêm một giải thích ngắn cho bài đăng. –

+0

CẢM ƠN bạn! Bạn nói "... cho trình liên kết biết phần nào (nếu có) là những phần đầu tiên cần xem xét". Tại sao một phần không có sẵn nếu nó được đánh dấu là KEEP? Có lẽ tôi đang thiếu một số nguyên tắc cơ bản ở đây, nhưng chủ đề này thực sự là mơ hồ (chưa quan trọng) và tôi gặp khó khăn trong việc tìm kiếm nguồn lực để giáo dục bản thân mình. – Sabuncu

7

Minimal Linux IA-32 ví dụ minh họa sử dụng của nó

main.S:

.section .text 
.global _start 
_start: 
    /* Dummy access so that after will be referenced and kept. */ 
    mov after, %eax 
    /*mov keep, %eax*/ 

    /* Exit system call. */ 
    mov $1, %eax 

    /* Take the exit status 4 bytes after before. */ 
    mov $4, %ebx 
    mov before(%ebx), %ebx 

    int $0x80 

.section .before 
    before: .long 0 
/* TODO why is the `"a"` required? */ 
.section .keep, "a" 
    keep: .long 1 
.section .after 
    after: .long 2 

liên kết.ld:

ENTRY(_start) 
SECTIONS 
{ 
    . = 0x400000; 
    .text : 
    { 
     *(.text) 
     *(.before) 
     KEEP(*(.keep)); 
     *(.keep) 
     *(.after) 
    } 
} 

Biên dịch và chạy:

as --32 -o main.o main.S 
ld --gc-sections -m elf_i386 -o main.out -T link.ld main.o 
./main.out 
echo $? 

Output:

1 

Nếu chúng ta nhận xét ra dòng KEEP đầu ra là:

2 

Nếu một trong hai chúng tôi:

  • thêm một giả mov keep, %eax
  • loại bỏ --gc-sections

Sản lượng đi trở lại 1.

Thử nghiệm trên Ubuntu 14.04, Binutils 2.25.

Giải thích:

Không có tham chiếu đến các biểu tượng keep, và do đó có chứa nó phần .keep.

Do đó, nếu thu thập rác được bật và chúng tôi không sử dụng KEEP để tạo ngoại lệ, phần đó sẽ không được đưa vào tệp thực thi.

Vì chúng tôi đang thêm 4 vào địa chỉ before, nếu không có phần keep thì trạng thái thoát sẽ là 2, xuất hiện ở phần .after tiếp theo.

TODO: không có gì xảy ra nếu chúng tôi xóa "a" từ .keep, điều này làm cho nó có thể phân bổ. Tôi không hiểu tại sao lại như vậy: phần đó sẽ được đặt bên trong phân đoạn .text, vì đó là tên ma thuật sẽ được phân bổ.

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