символ без имени и завершен.7392 символ в разделе .bss - PullRequest
0 голосов
/ 12 марта 2020

В моей программе C, скомпилированной с помощью g cc, секция .bss имеет индекс [24], как показано readelf -S. Когда я пытаюсь увидеть вещи, хранящиеся в .bss, запустив readelf -s ./pointer | grep 24, я получаю

Num:    Value          Size Type    Bind   Vis      Ndx Name
24: 00000000000040a0     0 SECTION LOCAL  DEFAULT   24
31: 00000000000040a8     1 OBJECT  LOCAL  DEFAULT   24 completed.7392
54: 00000000000040b0     8 OBJECT  GLOBAL DEFAULT   24 label
68: 00000000000040c0     0 NOTYPE  GLOBAL DEFAULT   24 _end
70: 00000000000040b8     4 OBJECT  GLOBAL DEFAULT   24 i
71: 0000000000004090     0 NOTYPE  GLOBAL DEFAULT   24 __bss_start
79: 00000000000040ac     4 OBJECT  GLOBAL DEFAULT   24 err
81: 00000000000040a0     8 OBJECT  GLOBAL DEFAULT   24 stderr@@GLIBC_2.2.5

size ./pointer дает мне

text      data     bss     dec     hex  filename
3196       680      32    3908     f44  ./pointer

что такое символ без имени и символ с именем completed.7392? и почему размер не добавляет до 32 байтов, как показано size? [сейчас 25]

В качестве дополнительного вопроса, где находятся символы stdin и stdout? Я могу найти только stderr, и это в разделе bss.

исходный текст программы прилагается ниже. скомпилировано с g cc версия 9.2

/*
 * A program that will read and print printable characters in it's memory given a memory address
 * until it segfaults
 */
#define _GNU_SOURCE /* Bring REG_XXX names from /usr/include/sys/ucontext.h */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <ucontext.h>

int i,err=0;
void sighandler(int signum);
void* label;

void readmem(){
    long loc;
    i=0;
    err=0;
    printf("enter mem location:");
    scanf("%lx",&loc);
    printf("--dump begin--\n");         
    char * addr = (void *) loc;
    char ch;
    label=&&l; 
/*  was kept there so that I can find how many bytes to increment rip to recover fro segfault
    address can be found using gdb also
*/
    while(1){
        ch=addr[i];
l:
        printf("%c",ch);
        i++;
        if ( err == 1)
            break;
//      printf("%d\n",i);
    }
}

static void sigaction_segv(int signal, siginfo_t *si, void *arg)
{
    ucontext_t *ctx = (ucontext_t *)arg;

    /* We are on linux x86, the returning IP is stored in RIP (64bit) or EIP (32bit).
    In this example, the length of the offending instruction is 6 bytes.
    So we skip the offender ! 

    &&l will return address pointed by label l
    (gdb) disass readmem
    ...
    0x0000555555555284 <+139>:  mov    -0x10(%rbp),%rax
    0x0000555555555288 <+143>:  add    %rdx,%rax
     => 0x000055555555528b <+146>:  movzbl (%rax),%eax              -> rip on segfault
    0x000055555555528e <+149>:  mov    %al,-0x19(%rbp)
    0x0000555555555291 <+152>:  movsbl -0x19(%rbp),%eax
    0x0000555555555295 <+156>:  mov    %eax,%edi
    0x0000555555555297 <+158>:  callq  0x555555555030 <putchar@plt>
    ...
    >>
    (gdb) p (void*) label
    $1 = (void *) 0x555555555291 <readmem+152>      ->address of next instruction
    >>

    we need to go to <readmem+152> ie, next instruction
    so we add decimal 6 to rip in sighandler
    */
    #if __WORDSIZE == 64
        printf("\nCaught SIGSEGV, addr %p, RIP 0x%lx\n",si->si_addr,ctx->uc_mcontext.gregs[REG_RIP]);
        ctx->uc_mcontext.gregs[REG_RIP] += 6;
    #else
        printf("Caught SIGSEGV, addr %p, EIP 0x%x\n",si->si_addr,ctx->uc_mcontext.gregs[REG_EIP]);
        ctx->uc_mcontext.gregs[REG_EIP] += 6;
    #endif 
    err=1;
    printf("no of bytes read:%d\n",i);
}


int main () {

    // 0x0 is hex literal that defaults to signed integer
    // here we are casting it to a void pointer
    // and then assigning it to a value declared to be a void pointer
    // this is the correct way to create an arbitrary pointer in C
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = sigaction_segv;
    sa.sa_flags = SA_SIGINFO;
    if (sigaction(SIGSEGV, &sa, NULL) == -1) {
        fprintf(stderr, "failed to setup SIGSEGV handler\n");
            exit(1);
    }
    char c[25];
    sprintf(c,"cat /proc/%d/maps",getpid());
    system(c);
    while(1){
        readmem();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...