2012-05-02 24 views
5

Phân tích Dump cốt lõi trong xây dựng bán lẻ thường yêu cầu phải tương quan objdump của bất kỳ mô-đun cụ thể nào và nguồn. Thông thường, tương quan với bãi chứa lắp ráp với nguồn sẽ trở thành một cơn đau nếu chức năng này khá liên quan. Hôm nay tôi đã cố gắng tạo ra một assembly listing của một mô-đun cụ thể (với tùy chọn biên dịch -S) mong đợi tôi sẽ thấy một nguồn xen kẽ với lắp ráp hoặc một số tương quan. Đáng tiếc là việc niêm yết vẫn chưa đủ thân thiện để tương quan vì vậy tôi đã tự hỏiNguồn tương ứng với Danh sách hội của Chương trình C++

  • Cho một lõi-dump mà từ đó tôi có thể xác định vị trí tai nạn
  • objdump của các mô-đun không hội Liệt kê theo biên dịch lại các module
  • với -S tùy chọn.

Có thể thực hiện tương tác một-với-một với nguồn không?

Như một ví dụ tôi thấy danh sách lắp ráp như

.LBE7923: 
     .loc 2 4863 0 
     movq %rdi, %r14 
     movl %esi, %r12d 
     movl 696(%rsp), %r15d 
     movq 704(%rsp), %rbp 
.LBB7924: 
     .loc 2 4880 0 
     testq %rdx, %rdx 
     je  .L2680 
.LVL2123: 
     testl %ecx, %ecx 
     jle  .L2680 
     movslq %ecx,%rax 
     .loc 2 4882 0 
     testl %r15d, %r15d 
     .loc 2 4880 0 
     leaq (%rax,%rax,4), %rax 
     leaq -40(%rdx,%rax,8), %rdx 
     movq %rdx, 64(%rsp) 

nhưng không thể hiểu làm thế nào để giải thích các nhãn như .LVL2123, chỉ thị như .loc 2 4863 0

Note Như câu trả lời mô tả, đọc qua nguồn lắp ráp và xác định trực giác mô hình dựa trên các biểu tượng (như các cuộc gọi hàm, các nhánh, trả về) là những gì tôi thường làm. Tôi không phủ nhận rằng nó không hoạt động nhưng khi một hàm khá tham gia, việc đọc các trang của Assembly Listing là một nỗi đau và thường bạn kết thúc với danh sách hiếm khi khớp hoặc vì các hàm nhận được trong hàng hoặc trình tối ưu hóa chỉ đơn giản là ném mã như nó hài lòng. Tôi có một cảm giác nhìn thấy hiệu quả như thế nào Valgrind xử lý các tệp nhị phân được tối ưu hóa và cách Windows WinDBG có thể xử lý các tệp nhị phân được tối ưu hóa, có một số thứ tôi thiếu. Vì vậy, tôi mặc dù tôi sẽ bắt đầu với đầu ra trình biên dịch và sử dụng nó để tương quan. Nếu trình biên dịch của tôi chịu trách nhiệm về xâu chuỗi nhị phân, nó sẽ là người tốt nhất để nói cách tương quan với nguồn, nhưng tiếc là điều đó ít hữu ích nhất và .loc thực sự gây hiểu nhầm. Thật không may tôi thường xuyên phải đọc qua các bãi không thể sản xuất trên nhiều nền tảng khác nhau và thời gian ít nhất tôi bỏ ra là gỡ lỗi Windows Mini-dumps mặc dù WinDBG và thời gian đáng kể trong việc gỡ lỗi Linux Coredumps. Tôi mặc dù có thể là tôi không làm những việc chính xác vì vậy tôi đã đưa ra câu hỏi này.

+0

Đây không phải là câu trả lời cho câu hỏi của bạn nhưng có thể hữu ích: http://msdn.microsoft.com/en-us/library/aa238730%28v=vs.60%29.aspx –

+1

Kết xuất lõi nên có địa chỉ trong đó. Vì vậy, hãy thử chương trình 'addr2line' để dịch sang vị trí nguồn. Điều này tất nhiên đòi hỏi một thực thi với các biểu tượng gỡ lỗi (nó sẽ hoạt động ngay cả khi phiên bản phân phối của bạn đã bị tước, chỉ cần so sánh với một phiên bản không bị tước) –

+0

@ edA-qamort-ora-y: Tôi sẽ thử điều này và cho bạn biết Tôi kết thúc với. BTW, shouldn; t này là một câu trả lời chứ không phải là một bình luận? – Abhijit

Trả lời

4

Có thể làm một one-to-one tương ứng với nguồn?

A: không, trừ khi tối ưu hóa tất cả bị tắt. Trình biên dịch có thể phát ra một số nhóm hướng dẫn (hoặc hướng dẫn giống như mọi thứ) trên mỗi dòng ban đầu, nhưng trình tối ưu hóa sau đó sắp xếp lại, chia tách, cầu chì và thường thay đổi chúng hoàn toàn.


Nếu tôi tháo mã phát hành, tôi xem hướng dẫn cần có mối quan hệ hợp lý rõ ràng với mã. Ví dụ:

.LBB7924: 
     .loc 2 4880 0 
     testq %rdx, %rdx 
     je  .L2680 

trông giống như một chi nhánh nếu %rdx là số không, và nó xuất phát từ dòng 4880. Tìm dòng, xác định các biến đang được thử nghiệm, làm cho một lưu ý rằng nó hiện đang giao cho %rdx.

.LVL2123: 
     testl %ecx, %ecx 
     jle  .L2680 

OK, vì vậy thử nghiệm này và chi nhánh có cùng một mục tiêu, vì vậy bất cứ đi tới biết %rdx%ecx đều khác không. Mã gốc có thể được cấu trúc như:

if (a && b) { 

hoặc có lẽ đó là:

if (!a || !b) { 

và optimizer sắp xếp lại hai chi nhánh ...

Bây giờ bạn đã có một số cấu trúc, bạn có thể hy vọng phù hợp với mã ban đầu, bạn cũng có thể tìm ra các bài tập đăng ký. Ví dụ, nếu bạn biết điều đang được thử nghiệm là thành viên dữ liệu của một số cấu trúc, đọc ngược lại để xem nơi %rdx được nạp từ bộ nhớ: nó được nạp từ một bù đắp cố định cho một số đăng ký khác? Nếu vậy, đăng ký đó có lẽ là địa chỉ đối tượng.

Chúc may mắn!

+0

+1 để biết hướng dẫn chi tiết. Nó thực sự tuyệt vời. Nhưng tiếc là điều này và chủ yếu là những gì @ Chris đã đề cập là những gì tôi làm để đọc qua bãi chứa. Nhưng bạn sẽ đồng ý, đọc qua các trang của bãi có thể đôi khi trở thành một nỗi đau thực sự và trên tất cả khi chức năng được in-lót. Ví dụ, hôm nay tôi gần như dành một giờ để đọc gần 1000 dòng hội. Tôi đã có một linh cảm rằng nên có một cái gì đó tôi đang thiếu xem xét như thế nào hiệu quả và gần như dự đoán 'Valgrind' bản đồ một nhị phân tối ưu hóa đầy đủ với danh sách nguồn nếu bạn biên dịch với tùy chọn' -g' (với các biểu tượng). – Abhijit

+0

Vâng, nhãn '.loc' có thể ánh xạ một nhóm các chỉ lệnh tới một dòng mã, và có lẽ valgrind có thể sử dụng nó để gán chi phí lệnh xấp xỉ cho một dòng nguồn. Tuy nhiên, điều đó không giống như tìm ra lý do tại sao một chương trình bị lỗi: bạn đang cố gắng xây dựng lại trạng thái chương trình _logical_ mà trình tối ưu hóa đã chuyển đổi và loại bỏ. Đó là khó khăn hơn, và không cần thiết cho kế toán valgrind. – Useless

4

Chỉ thị .loc là những gì bạn đang tìm kiếm. Những dòng này cho biết # 4863, 4880, v.v. Không có ánh xạ hoàn hảo giữa nguồn và trình tối ưu hóa (đó là lý do tại sao bạn thấy 4880 nhiều hơn một lần). Nhưng .loc là cách bạn biết vị trí của nó trong tệp. Cú pháp là:

.loc <file> <line> <column> 
+0

Có phải bất cứ thứ gì tôi có thể phỏng đoán ở đây không? Ví dụ, '.loc' có hai số khác như' 2' và '0'. Cái gì đây? Và các nhãn này là gì .LVL2123' và '.LBE7923'? – Abhijit

+1

Đó thường là các mục tiêu 'goto' phát ra bởi trình biên dịch. Ví dụ bạn có 'je .L2680', vì vậy nên có một dòng bắt đầu' .L2680: 'ở đâu đó. – Useless

1

Trừ khi bạn liên kết tĩnh với thư viện hệ thống, ngay cả khi không có biểu tượng gỡ lỗi, sẽ có tên biểu tượng trong nhị phân - đó là các hàm thư viện hệ thống được liên kết đến.

Những điều này thường có thể giúp thu hẹp vị trí của bạn trong mã. Ví dụ, nếu bạn thấy rằng trong hàm foo() nó gọi open() và sau đó ioctl() và sau đó nó đổ vỡ ngay trước khi gọi hàm read(), bạn có thể thấy điểm đó trong nguồn của foo khá dễ dàng. (Cho rằng vấn đề bạn thậm chí có thể không cần dump - trên linux bạn có thể nhận được hồ sơ của sự cố xảy ra liên quan đến thư viện và hệ thống chức năng sử dụng ltrace hoặc strace)

Lưu ý rằng trong một số định dạng nhị phân mặc dù, có thể có một indirection đến các hàm thư viện thông qua các trình bao bọc nhỏ ở nơi khác trong tệp nhị phân. Thường thì một bãi chứa sẽ vẫn có thông tin tên biểu tượng có liên quan tại địa chỉ của lời gọi trong luồng chương trình. Nhưng ngay cả khi không, bạn có thể nhận ra những trình bao bọc liên kết bên ngoài này bằng phạm vi địa chỉ của chúng trong nhị phân và khi bạn thấy một địa chỉ, bạn có thể tìm mã của nó và tìm ra hàm bên ngoài nó liên kết tới. Tuy nhiên, như những người khác đã đề cập, nếu bạn có mã nguồn và hệ thống bị treo thường xuyên đủ để hữu ích, đặt cược nhanh nhất của bạn thường là xây dựng lại bằng biểu tượng gỡ lỗi hoặc chèn đầu ra ghi nhật ký và nhận được sự cố hữu ích hơn ghi lại.

+0

Thật không may tôi thường phải gỡ lỗi các bãi không thể sản xuất trên các hệ thống khác nhau và những gì bạn đề cập là cách tôi làm và nó hoạt động nhưng tôi phải đầu tư rất nhiều công sức và thời gian. Tôi đã ước tính rằng việc gỡ lỗi Windows Mini-dump tốn ít thời gian hơn (thông qua WinDBG) so với gỡ lỗi coredump Linux. Thậm chí đau đớn cũng đang gỡ lỗi các bãi Solaris/AIX/HP-UX. Thấy Valgrind hiệu quả như thế nào để ánh xạ một hệ nhị phân được tối ưu hóa với nguồn tôi thực sự tham vọng và lạc quan về việc xác định một cái gì đó hiệu quả hơn. @ edA-qa mort-ora-y đã có một gợi ý rằng tôi chưa thử và cho bạn biết nơi tôi kết thúc bằng :-) – Abhijit