我在远程计算机上运行程序,我只能使用stdout进行交互。我在程序的某个地方有一个段错误,我试图弄清楚在哪里。是否有可能为sigsegv编写一个信号处理程序,它给出了行号和发生它的文件?
答案 0 :(得分:3)
这听起来像是一个糟糕的调试环境,但如果让GDB运行真的不可行,你可以试试以下(假设Linux):
SIGSEGV
,SIGBUS
或您认为致命信号使用sigaction()
的任何内容注册处理程序,并传递sa.sa_flags = SA_SIGINFO
。使用sa_sigaction
而非sa_handler
struct sigaction
成员注册处理程序。void *context
参数。假设X86_64(您必须弄清楚其他体系结构上指令指针的相应索引),您可以通过((ucontext_t*)context)->uc_mcontext.gregs[REG_RIP]
获取触发信号的地址。addr2line -Cfip -e <binary with debugging symbols> <address>
获取功能和行号。 (如果您要进行交叉编译,则需要使用工具链中的addr2line
,这可能会有一些前缀,例如arm-linux-androideabi-addr2line
。)(顺便说一下,我刚从另一个问题中回忆起context
信号处理程序参数。:)
上述方法的一个限制是,它可能不会为您提供库中崩溃的行号 - 特别是如果它们在随机地址中加载。
另一种方法是使用backtrace(3)
,这可以在glibc和其他一些libc中使用。有点hackish,但你可以把你从它获得的地址(作为字符串)写到popen("addr2line -Cfip -e <binary with debugging symbols>")
(/proc/self/exe
也可以在Linux上使用)来生成stdout
上的行号的回溯。 backtrace_symbols_fd()
也值得研究,虽然它不会给你行号。编译时需要-rdynamic
。
修改强>
似乎GDB使用personality(2)
和ADDR_NO_RANDOMIZE
来转换库的地址空间随机化(将需要后跟re - execve()
)。如果你真的很绝望,也许(或/proc/sys/kernel/randomize_va_space
)也可以用来获取图书馆内的行号。