Làm cách nào để tạo biểu tượng gỡ lỗi gcc bên ngoài mục tiêu xây dựng?


176

Tôi biết tôi có thể tạo biểu tượng gỡ lỗi bằng tùy chọn -g. Tuy nhiên, biểu tượng được nhúng trong tệp mục tiêu. Gcc có thể tạo biểu tượng gỡ lỗi bên ngoài thư viện thực thi / thư viện không? Giống như tập tin .pdb của trình biên dịch VC ++ đã làm.

Câu trả lời:


184

Bạn cần sử dụng objcopy để tách thông tin gỡ lỗi :

objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"

Tôi sử dụng tập lệnh bash bên dưới để phân tách thông tin gỡ lỗi thành các tệp có phần mở rộng .debug trong thư mục .debug. Bằng cách này, tôi có thể tar các thư viện và các tệp thực thi trong một tệp tar và các thư mục .debug trong một tệp khác. Nếu tôi muốn thêm thông tin gỡ lỗi sau này, tôi chỉ cần giải nén tệp tar gỡ lỗi và voila, tôi có thông tin gỡ lỗi tượng trưng.

Đây là tập lệnh bash:

#!/bin/bash

scriptdir=`dirname ${0}`
scriptdir=`(cd ${scriptdir}; pwd)`
scriptname=`basename ${0}`

set -e

function errorexit()
{
  errorcode=${1}
  shift
  echo $@
  exit ${errorcode}
}

function usage()
{
  echo "USAGE ${scriptname} <tostrip>"
}

tostripdir=`dirname "$1"`
tostripfile=`basename "$1"`


if [ -z ${tostripfile} ] ; then
  usage
  errorexit 0 "tostrip must be specified"
fi

cd "${tostripdir}"

debugdir=.debug
debugfile="${tostripfile}.debug"

if [ ! -d "${debugdir}" ] ; then
  echo "creating dir ${tostripdir}/${debugdir}"
  mkdir -p "${debugdir}"
fi
echo "stripping ${tostripfile}, putting debug info into ${debugfile}"
objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"
chmod -x "${debugdir}/${debugfile}"

8
Nếu bạn gặp vấn đề trong sản xuất và cần đính kèm quy trình với gdb, bạn có thể cung cấp tệp biểu tượng gỡ lỗi cho GDB không? Và làm thế nào, nếu vậy? thnx
yves Baume

3
@yves Baume Chỉ cần thêm thư mục .debug với các tệp .debug vào hộp sản xuất của bạn và GDB sẽ chọn chúng. Sau phiên gỡ lỗi, bạn có thể xóa chúng một lần nữa.
lothar

Tham khảo @Lance Richardson trả lời bình luận cho một ví dụ.
Giáo sư

7
Có phải cũng có thể khôi phục tệp nhị phân gốc (ví dụ: tệp nhị phân bị tước + tệp .debug = tệp nhị phân gốc) không?
Paul Praet

1
Bạn có tìm thấy bất kỳ vấn đề với bỏ qua --build-idtùy chọn liên kết ?
jww

110

Biên dịch với thông tin gỡ lỗi:

gcc -g -o main main.c

Phân tách thông tin gỡ lỗi:

objcopy --only-keep-debug main main.debug

hoặc là

cp main main.debug
strip --only-keep-debug main.debug

Dải thông tin gỡ lỗi từ tệp gốc:

objcopy --strip-debug main

hoặc là

strip --strip-debug --strip-unneeded main

gỡ lỗi bằng chế độ gỡ lỗi:

objcopy --add-gnu-debuglink main.debug main
gdb main

Bạn cũng có thể sử dụng tệp exec và tệp ký hiệu riêng biệt:

gdb -s main.debug -e main

hoặc là

gdb
(gdb) exec-file main
(gdb) symbol-file main.debug

Để biết chi tiết:

(gdb) help exec-file
(gdb) help symbol-file

Tham khảo:
https://sourceware.org/gdb/onlinesocs/gdb/Files.html#Files https://sourceware.org/gdb/onlinesocs/gdb/Separate-Debug-Files.html


2
Và bạn nên sử dụng objcopy --add-gnu-debuglink main main.debugđể nhúng tên của tệp gỡ lỗi đã tạo và tổng kiểm tra. Trong trường hợp này, gdb sẽ cố gắng tự tìm mã gỡ lỗi trong một vài vị trí phụ thuộc vào phân phối, không còn tùy chọn -s nữa.
Lothar

9

Kiểm tra tùy chọn "--only-keep-debug" của lệnh dải .

Từ liên kết:

Mục đích là tùy chọn này sẽ được sử dụng cùng với --add-gnu-debuglink để tạo ra một phần thực thi hai phần. Một tệp nhị phân bị tước sẽ chiếm ít dung lượng trong RAM và trong bản phân phối và tệp thứ hai là tệp thông tin gỡ lỗi chỉ cần nếu khả năng gỡ lỗi là bắt buộc.


1
Có, tôi đã thử nó: gcc -ggdb -o test test.c; kiểm tra cp test.debug; dải --only-keep-debug test.debug; kiểm tra dải; objcopy --add-gnu-debuglink = test.debug test; Sau đó, bạn có thể gỡ lỗi kiểm tra
zhaorufei

8

LƯU Ý: Các chương trình được biên dịch với mức tối ưu hóa cao (-O3, -O4) không thể tạo nhiều ký hiệu gỡ lỗi cho các biến được tối ưu hóa, các hàm được xếp hàng và các vòng lặp không được kiểm soát, bất kể các ký hiệu được nhúng (-g) hoặc trích xuất (objcopy) vào một Tập tin '.debug'.

Phương pháp thay thế là

  1. Nhúng dữ liệu phiên bản (VCS, git, svn) vào chương trình, để thực thi tối ưu hóa trình biên dịch (-O3, -O4).
  2. Xây dựng phiên bản thứ 2 không được tối ưu hóa của tệp thực thi.

Tùy chọn đầu tiên cung cấp một phương tiện để xây dựng lại mã sản xuất với đầy đủ gỡ lỗi và ký hiệu vào một ngày sau đó. Có thể xây dựng lại mã sản xuất ban đầu mà không cần tối ưu hóa là một trợ giúp to lớn để gỡ lỗi. (LƯU Ý: Giả định này đã được thực hiện với phiên bản tối ưu hóa của chương trình).

Hệ thống xây dựng của bạn có thể tạo tệp .c được tải cùng với ngày biên dịch, cam kết và các chi tiết VCS khác. Dưới đây là ví dụ 'make + git':

program: program.o version.o 

program.o: program.cpp program.h 

build_version.o: build_version.c    

build_version.c: 
    @echo "const char *build1=\"VCS: Commit: $(shell git log -1 --pretty=%H)\";" > "$@"
    @echo "const char *build2=\"VCS: Date: $(shell git log -1 --pretty=%cd)\";" >> "$@"
    @echo "const char *build3=\"VCS: Author: $(shell git log -1 --pretty="%an %ae")\";" >> "$@"
    @echo "const char *build4=\"VCS: Branch: $(shell git symbolic-ref HEAD)\";" >> "$@"
    # TODO: Add compiler options and other build details

.TEMPORARY: build_version.c

Sau khi chương trình được biên dịch, bạn có thể xác định vị trí 'cam kết' ban đầu cho mã của mình bằng cách sử dụng lệnh: strings -a my_program | grep VCS

VCS: PROGRAM_NAME=my_program
VCS: Commit=190aa9cace3b12e2b58b692f068d4f5cf22b0145
VCS: BRANCH=refs/heads/PRJ123_feature_desc
VCS: AUTHOR=Joe Developer  joe.developer@somewhere.com
VCS: COMMIT_DATE=2013-12-19

Tất cả những gì còn lại là kiểm tra mã gốc, biên dịch lại mà không tối ưu hóa và bắt đầu gỡ lỗi.


3
-O4thậm chí không tồn tại.
Hi-Angel

3
Rất tiếc, có thể là từ ngày 'suncc', trong đó '-O5' thậm chí là một tùy chọn. Đây là một liên kết đến các tùy chọn gcc4.4.7 -O: gcc.gnu.org/onlinesocs/gcc-4.4.7/gcc/ Kẻ
J Jorgenson

3
Điều này không giải quyết vấn đề phổ biến là cố gắng diễn giải một bãi chứa lõi có thể không dễ tái tạo. Lời khuyên trong câu trả lời này là âm thanh, nhưng nó không giải quyết được câu hỏi.
David Rodríguez - dribeas

4

Không có câu trả lời cho đến nay đề cập eu-strip --strip-debug -f <out.debug> <input>.

  • Điều này được cung cấp bởi elfutilsgói.
  • Kết quả sẽ là <input>tập tin đó đã bị tước bỏ các biểu tượng gỡ lỗi hiện đang có <out.debug>.
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.