c-gdb-如何使用gdb捕获损坏



我正在努力查找新程序中何时何地发生损坏。这个程序只有495行,gdb没有帮我调试它

> gdb psgrep-2020
(comments omitted)
Reading symbols from psgrep-2020...
(gdb) b 466
Breakpoint 1 at 0x3073: file psgrep-2020.c, line 466.
(gdb) run -F dnsmasq
Starting program: /usr/local/src/psgrep-2022/psgrep-2020 -F dnsmasq
Breakpoint 1, showProcess (pid=893) at psgrep-2020.c:466
466         if (printCmdline) {
(gdb) step
467             procNameFromCmdline(pid, strWork, sizeof(strWork), TRUE) ;
(gdb) p pid
$1 = 893
(gdb) p strWork
$2 = '00' <repeats 1023 times>
(gdb) print sizeof(strWork)
$3 = 1024
(gdb) step
procNameFromCmdline (pid=0, result=0x0, resultLen=0, fullCmd=0 '00') at psgrep-2020.c:58
58  int procNameFromCmdline(pid_t pid, char *result, int resultLen, BOOL fullCmd) {
(gdb) 

在调用进程(procNameFromCmdline(开始时,我们可以看到每个参数都是不正确的(通过#define,TRUE等于1(。有时gdb显示如下:

procNameFromCmdline (pid=0, result=0x19c5b4 <error: Cannot access memory at address 0x19c5b4>, resultLen=1689012, fullCmd=0 '00') 

我不是想让别人替我找问题;我想做的是找到一种方法,当程序被破坏时,我可以检测到。我相信我所有的memset、snprintf((等等都受到了正确的约束;显然是出了问题。

如果有任何帮助并正确看待问题,以下是调用之前的相关代码。。。

fpProcFile = fopen(sProcPath, "rt") ; // Open the stat file for reading text
if (fpProcFile) {
fscanf(fpProcFile
, "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld "
"%ld %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u "
"%u %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %d"
, &(s->pid),           s->comm,       &(s->state),       &(s->ppid),        &(s->pgrp)
, &(s->session),     &(s->tty_nr),    &(s->tpgid),       &(s->flags),       &(s->minflt)
, &(s->cminflt),     &(s->majflt),    &(s->cmajflt),     &(s->utime),       &(s->stime)
, &(s->cutime),      &(s->cstime),    &(s->priority),    &(s->nice),        &(s->num_threads)
, &(s->itrealvalue), &(s->starttime), &(s->vsize),       &(s->rss),         &(s->rsslim)
, &(s->startcode),   &(s->endcode),   &(s->startstack),  &(s->kstkesp),     &(s->kstkeip)
, &(s->signal),      &(s->blocked),   &(s->sigignore),   &(s->sigcatch),    &(s->wchan)
, &(s->nswap),       &(s->cnswap),    &(s->exit_signal), &(s->processor),   &(s->rt_priority)
, &(s->policy),      &(s->delayacct_blkio_ticks)
,  &(s->guest_time),  &(s->cguest_time), &(s->start_data)
, &(s->end_data),    &(s->start_brk), &(s->arg_start),   &(s->arg_end),     &(s->env_start)
, &(s->env_end),     &(s->exit_code)
) ;
fclose(fpProcFile) ;
processName = s->comm ;
memset(strWork, 0x00, sizeof(strWork)) ;
if (printCmdline) {
procNameFromCmdline(pid, strWork, sizeof(strWork), TRUE) ;

(fscanf中唯一的%s指向一个字符[665535],/fproc/893/stat中该字段的值长度为9加上一个终止符。根据文档,16就足够了。但这不是重点。(

有办法吗?我需要更专业的调试器吗?

(虽然我不是在找人来解决这个程序的问题,但它似乎已经引起了一些兴趣。从这个角度来看,我发布了引用代码中使用的结构。(这在linux内核源代码(fs/proc/array.c(中有文档记录,(不是我的版本(可以在[这里][1]和许多其他地方看到。

struct myProcStat {
int pid ;       // Process ID
char comm[65535] ; // Command name limited to 16 bytes
char state ;    // R=Running S=Sleeping D=WaitingDisk Z=Zombie T=Stopped 
// t=TracingStopped W=Paging X=Dead x=Dead K=Wakekill
// W=Waking P=Parked
int ppid ;      // Parent process ID
int pgrp ;      // Process group ID
int session ;   // Session ID
int tty_nr ;    // Controlling terminal
int tpgid ;     // Foreground process group
unsigned int flags ; // Kernel flags
unsigned long int minflt ; // Number of minor faults
unsigned long int cminflt ; // Children's minor faults
unsigned long int majflt ; // Number of major faults
unsigned long int cmajflt ; // Children's major faults
unsigned long int utime ; // Amount of time scheduled user mode
unsigned long int stime ; // Amount of time scheduled kernel mode
long int cutime ;   // Amount of time waited-for children scheduled user mode
long int cstime ;   // Amount of time waited-for children scheduled kernel mode
long int priority ; // Priority running real-time scheduling policy
long int nice ;     // Nice value
long int num_threads ; // Number of threads in this process
long int itrealvalue ; // Time in jiffies before next SIGALARM is sent
// 21 above, 22 next ...
unsigned long long int starttime ; // Start tine (in clock ticks) after system boot (divide by sysconf(_SC_CLK_TCK))
unsigned long int vsize ; // Virtual memory size in bytes
long int rss ;  // Resident set size
unsigned long int rsslim ; // Current soft limit in bytes on rss
unsigned long int startcode ; // address above which text can be run
unsigned long int endcode ;   // Address below which text can be run
unsigned long int startstack ; // Address of the start (bottom) of the stack
unsigned long int kstkesp ; // Current stack pointer from kernel perspective
unsigned long int kstkeip ; // Current EIP (instruction pointer)
unsigned long int signal ; // Bitmap of pending signals as a decimal number. Obsolete. use /proc/[pid]/status instead.
unsigned long int blocked ; // Bitmap of blocked signals. Obsolete. Use /proc/[pid]/status instead
unsigned long int sigignore ; // Bitmap of ignored signals. Obsolete, use /proc/[pid]/status instead
unsigned long int sigcatch ; // Bitmap of caught signals.  Use /proc/[pid]/status instead
unsigned long int wchan ; // Channel in which process is waiting. Use with /proc/[pid]/wchan
unsigned long int nswap ; // Number of pages swapped (not maintained - ignore)
unsigned long int cnswap ; // Number of child process pages swapped (not maintained - ignore)
int exit_signal ; // Signal to be sent to parent upon death
int processor ;   // CPU last executed on
unsigned int rt_priority ; // Real-time scheduling priority
unsigned int policy ; // Scheduling policy for real-time scheduling
unsigned long long int delayacct_blkio_ticks ; // Aggregated block I/O delays, in clock ticks
unsigned long int guest_time ; // Guest time (time spent running virtual CPU for guest OS)
unsigned long int cguest_time ; // Guest time of processes' children
unsigned long int start_data ; // Address above which program BSS data are placed
unsigned long int end_data ; // Address below which program BSS data are placed
unsigned long int start_brk ; // Address above which program heap can be expanded
unsigned long int arg_start ; // Address above which program command-line arguments (argv) are placed
unsigned long int arg_end ; // Address below which argv are placed
unsigned long int env_start ; // Address above which environment is placed
unsigned long int env_end ; // Address below which environment is placed
int exit_code ; // The thread's exit status in form reported by waitpid(2)
} ;

[1]: https://elixir.bootlin.com/linux/latest/source/fs/proc/array.c

在被调用进程(procNameFromCmdline(开始时,我们可以看到每个参数都是不正确的

这很可能意味着GDB没有跳过函数prolog(就像它应该跳过的那样(。很可能是因为这个。

如果您执行另一个stepnext,参数将突然再次变得正确。

请注意,上述错误已在较新的GDB版本中修复,因此更新GDB是另一种解决方案。

相关内容

  • 没有找到相关文章

最新更新