我应该使用哪些 gdb 命令来缩小标签“main”中出现分段错误的位置?

Posted

技术标签:

【中文标题】我应该使用哪些 gdb 命令来缩小标签“main”中出现分段错误的位置?【英文标题】:What gdb commands should I use to narrow down where in label 'main' did I get the segmentation fault? 【发布时间】:2019-12-05 17:39:30 【问题描述】:

这是我的汇编代码和我的主要子程序。 这是我的宏和常量:

             .text
fmt:         .string "x \t\t ln(x)\n"
sfmt:        .string "%.10lf \t %.10lf\n"
error:       .string "Error"
filename:    .string "input.bin"

             .data
LIM:         .double 0r1.0E-13
zero:        .double 0r0.0
one:         .double 0r1.0
half:        .double 0r0.5

define(i_r,w19)
define(j_r,w20)
define(n_r,w21)
define(fd_r,w22)
define(ln_x,d8)
define(cur_term,d24)
define(n_read,x25)
define(x_j,d26)

BUF_SIZE = 98*8
AT_FDCWD = -100
O_RDONLY = 0
buf_s = 16

          .bss
x_arr:    .skip   BUF_SIZE

fp        .req    x29
lr        .req    x30

          .balign 4
          .global main

这是我的主要子程序:

main:
       stp    fp,lr,[sp,-16]!
       mov    fp,sp

       ldp   fp,lr,[sp],16
       ret

我已经使用了 gdb,但是它只指出 SIGSEGV 信号来自 main() 中的 0x0000000000420358。如何缩小此信号的“主要​​”来源? P.S 我只知道 GDB 的基础知识。

GDB 资料:(更新)

(gdb) x/i $pc
=> 0x420358:    .inst   0x00000000 ; undefined

我不知道这是否有帮助,但这是可行的 C 版本。我正在将其转换为汇编,因为这就是我需要提交的内容。此外,我们不能使用任何类型的转换器,因为那被认为是作弊。

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>                                                                 //Used for the keyword for flags and other predefined values for the argument on openat,etc.

#define LIM         1.0e-13                                                     
#define DOUBSIZE    100                                                         //There are 97 double values in the binary file
#define buf_size    98*8                                                        
double x[DOUBSIZE];
int main() 
    register int i = 1,j = 0,fd = openat(AT_FDCWD,"input.bin",O_RDONLY);    //int fd = openat(int dirfd,const char *pathname (basically a string),int flags,mode_t mode);
    register double ln_x = 0.0,cur_term;
//double *x;        //(only local variable)                                         //(a local variable so it must be in the stack)only assuming there are 32 double precision values in the binary file
    register long n_read = read(fd,&x,buf_size);                            //reads in 8 bytes(lost the double x[...] in this line since x is now pointing at the buffer

    if(fd == -1) 
        printf("Error!");
        return 0;
    

    if(n_read == -1)                                                           //Error checker
        printf("Error!");                           
        return 0;                                   
                                               

    printf("x \t\t ln(x)\n");                                                   //The header of the thing to be printed

    while(j < (buf_size/8))                                                    //note that it is implied that EOF = -1 in C
        if(x[j] <= 0.5)                                                        //if x is less than or equal to 1/2,go to the next double value(assuming I don't know values in the bin file)
            j++;
            i = 1;
            continue;
        

        cur_term = (1.0/i) * (pow((double)((x[j]-1.0)/(x[j])),i));
        ln_x += cur_term;

        while(cur_term >= LIM)                                                 //continue to accumulate terms until the absolute value of the term is less than 1.0E-13
            i++;                                                                //follows the pattern of the series.
            cur_term = (1.0/i)*(pow((double)((x[j]-1.0)/(x[j])),i));            //since it should start with x[1]
            ln_x += cur_term;                                                   //adds the new term to previous ln(x) value
        

        printf("%.10lf \t %.10lf\n",x[j],ln_x);                                 //prints the current value of ln(x) and x
        j++;                                                                    //manages which x double value will be used next
        i = 1;
        ln_x = 0.0;
    

    close(fd);
    return 0;
 

【问题讨论】:

评论不用于扩展讨论;这个对话是moved to chat。 【参考方案1】:

原来你的main.bss 部分,而不是它所属的.text,所以它只能包含全零字节。 (而且它不会是可执行的)。

GDB 通常只想反汇编 .text 部分中的代码,这也说明 GDB 很奇怪。

这就是为什么您应该将代码缩减为 MCVE(最小 / 完整 / 可验证示例)以使其尽可能小,同时仍然包含问题。

【讨论】:

以上是关于我应该使用哪些 gdb 命令来缩小标签“main”中出现分段错误的位置?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 头文件上使用 gdb?

GDB调试实战(10)多线程调试

GDB调试——常用的命令

编写 GDB 脚本来收集数据

spacemacs 使用gdb

是否可以从 GDB 的外部文件中将命令注册到断点?