2009-06-24 24 views
7

Tại công ty của tôi, chúng tôi có một vấn đề thực sự gây phiền nhiễu với trình liên kết của chúng tôi (ld 2.17). Nó liên kết rất rất chậm trên một hệ thống tương đối nhanh (Core Duo, 2GB Ram) và tôi không thực sự bây giờ làm thế nào để sửa lỗi này. Mất khoảng 5 đến 10 phút để biên dịch một dự án tương đối lớn (mất khoảng 5 giây để liên kết trên hệ thống Gentoo của tôi).Làm thế nào để gỡ lỗi một liên kết (chậm) trên một hệ thống debian

Cá nhân tôi nghĩ rằng đó là một kẻ giết người năng suất rất lớn, ít nhất là đối với tôi. Chúng tôi đã cố gắng sử dụng phiên bản mới hơn của ld (2.19) nhưng không thành công. Tôi đã hỏi #debian trên #freenode, nhưng vấn đề này dường như rất độc đáo. Tôi không tìm thấy bất kỳ thông tin nào về các vấn đề tương tự trên mạng. Nó chỉ xảy ra khi chúng ta xây dựng với các biểu tượng gỡ lỗi. Tôi đã thay đổi cờ thông báo gỡ lỗi gcc thành -g, -g3 và -ggdb, nhưng điều đó cũng không giúp được gì.

Vì vậy, câu hỏi của tôi là, làm thế nào để bạn hồ sơ và gỡ lỗi một mối liên kết? Tôi chưa bao giờ làm bất cứ điều gì như nó, và tôi không thể tìm thấy bất kỳ tài liệu nào về nó. Về cơ bản bất kỳ gprof.out gprof hợp lý sẽ rất hữu ích, vì tôi có thể hỏi các nhà phát triển binutils về một vấn đề cụ thể. Tôi hoàn toàn không biết gì về điều này.

Chỉnh sửa: Chúng tôi đã khắc phục sự cố của chúng tôi khi chuyển sang debian lenny trên hầu hết các hệ thống. Cảm ơn câu trả lời!

Trả lời

5

Nếu bạn đang quan sát suy thoái chạy gcc (như trái ngược với trực tiếp chạy các mối liên kết như ld), thử biên dịch với

 
$ gcc -save-temps -v [... rest of your command line ...] 

này sẽ in ra tất cả các lệnh trung gian, chẳng hạn như nội collect2 và cuối cùng ld, cũng như đảm bảo rằng các đối tượng được truyền cho các lệnh đó sẽ vẫn còn trên đĩa ngay cả sau khi lệnh đã hoàn thành.

Sau đó, bạn sẽ có thể chạy các lệnh riêng lẻ để tìm giai đoạn tồi tệ nhất, và sau đó chạy nó với các tùy chọn hoặc lược tả khác nhau.

Ví dụ,

 
$ echo 'int main() {}' > test.c 
$ gcc -save-temps -v test.c 
Using built-in specs. 
Target: x86_64-pc-linux-gnu 
Configured with: /var/tmp/paludis/sys-devel-gcc-4.3.3-r2/work/gcc-4.3.3/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.3.3 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.3 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.3/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.3/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --enable-multilib --enable-libmudflap --disable-libssp --enable-libgomp --enable-cld --disable-libgcj --enable-objc-gc --enable-languages=c,c++,objc,obj-c++,treelang,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.3.3-r2 p1.1, pie-10.1.5' 
Thread model: posix 
gcc version 4.3.3 (Gentoo 4.3.3-r2 p1.1, pie-10.1.5) 
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic' 
/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/cc1 -E -quiet -v test.c -D_FORTIFY_SOURCE=2 -mtune=generic -fpch-preprocess -o test.i 
ignoring nonexistent directory "/usr/local/include" 
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/include" 
#include "..." search starts here: 
#include search starts here: 
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include 
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include-fixed 
/usr/include 
End of search list. 
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic' 
/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/cc1 -fpreprocessed test.i -quiet -dumpbase test.c -mtune=generic -auxbase test -version -o test.s 
GNU C (Gentoo 4.3.3-r2 p1.1, pie-10.1.5) version 4.3.3 (x86_64-pc-linux-gnu) 
     compiled by GNU C version 4.3.3, GMP version 4.2.4, MPFR version 2.4.1-p5. 
warning: GMP header version 4.2.4 differs from library version 4.3.1. 
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 
Compiler executable checksum: 20f3dbffbfd03e5311a257ae1239cd71 
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic' 
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/bin/as -V -Qy -o test.o test.s 
GNU assembler version 2.19.1 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.19.1 
COMPILER_PATH=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/libexec/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/libexec/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/bin/ 
LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../:/lib/:/usr/lib/ 
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic' 
/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../.. test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crtn.o 
$ ls 
a.out test.c test.i test.o test.s 
$ /usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../.. test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crtn.o 
$ .../collect2 -v ... 
collect2 version 4.3.3 (x86-64 Linux/ELF) 
/usr/bin/ld -v --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../.. test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crtn.o 
GNU ld (GNU Binutils) 2.19.1 
$ 

Nếu bạn cần giúp đỡ xây dựng một phiên bản debug của ld, đây là một công thức nhanh chóng để giúp bạn có được đi.

 
$ sudo apt-get install build-essential dpkg-dev 
$ sudo apt-get build-dep binutils 
$ apt-get source binutils 
$ cd binutils-* 
$ DEB_BUILD_OPTIONS='debug noopt nostrip' dpkg-buildpackage -uc -us 
$ cd .. 
$ sudo dpkg -i *.deb 

Thay vì đó hack nhanh chóng, tuy nhiên, tôi khuyên bạn nên sử dụng schroot hoặc sbuild để tránh gây ô nhiễm hệ thống của riêng bạn.

+0

+1 cho "hỗ trợ debian không rõ ràng" và cờ gcc :) – tr9sh

+0

@ephemient Tôi đang cố gắng chuyển sang nguồn ld.so và muốn xem dòng mã nguồn đang được thực thi trong GDB. Tôi đã cài đặt binutils-source và libcdbg nhưng GDB cho thấy SOurce không có sẵn khi điều khiển nhập mã ld.so. Bạn có thể vui lòng đề nghị những gì tôi đang thiếu. Cảm ơn http://stackoverflow.com/questions/20114565/gdb-step-into-dynamic-linkerld-so-code – abhi

6

Bạn có thể thử vàng (binutils-gold) thay vì ld. Nó được cho là nhanh hơn.

Dưới đây là một trích dẫn từ Wikipedia Gold(linker)

Động lực để viết vàng tức là tạo ra một mối liên kết đó là nhanh hơn so với GNU mối liên kết [3], đặc biệt là cho các ứng dụng lớn mã hóa trong C++.

Tác giả của vàng (Ian Lance Taylor) đã xuất bản các họa tiết viết vàng và tại sao hầu hết các liên kết đều chậm. Nếu bạn quan tâm đến hoạt động bên trong của linkers thì bài viết này đáng đọc.

+1

cảm ơn, tôi biết về vàng nhưng chúng tôi chưa sẵn sàng chuyển sang – tr9sh

3

Để trả lời câu hỏi định hình; bạn nên xem OProfile - đây là một trình lược tả cấp hệ thống có thể cấu hình nhiều quy trình đang chạy. Nó sẽ cho phép bạn xác định quy trình phụ của liên kết đang sử dụng nhiều nhất, và hơn thế nữa sẽ hiển thị các chức năng nào được sử dụng nhiều nhất.

1

Tôi muốn đề nghị hai cách để kiểm tra:

  1. sử dụng strace để kiểm tra những tập tin mối liên kết đang tải/phân tích cú pháp để liên kết; với điều này bạn có thể biết là có bất kỳ đường dẫn không cần thiết nào được tìm kiếm bởi trình liên kết.
  2. sử dụng tùy chọn ld with -verbose để biết ld đang làm gì. Năm phút so với năm giây không nên là vấn đề của người liên kết, nó sẽ là một số vấn đề của máy chủ của bạn hoặc một số tùy chọn.
Các vấn đề liên quan