2017-09-08 2 views
0

私はタイマーを開始するコードをデバッグするのにgdbを使用しています。 gdbのタイマーが鳴ると、私はいつもtimer_settime + 16という命令で終わります。 これが予想どおりの動作ですか?timer/signalでのデバッグは常に<timer_settime + 16>で終了する

例として、timer_settimeのマニュアルページのコードを少し修正しました。この考え方は、整数の文字列とnsecの値の2つの引数を渡すことです。コードは、タイマーを起動してn秒後に呼び出し、文字列をコピーします。 私は、コピーループの中で終わるために、異なるコード行で停止したnsec値をインクリメントすることによって、gdbが予想されました。しかしそれはいつもで止まる。

これが期待される動作ですか?

どこかに文書化されていますか?

私が期待したことを達成する方法がありますか(つまり、プログラムの直前(または後)にリングがgdbを停止させるタイマーを起動します)? (常にnsec粒度で)。

コード:

#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <signal.h> 
#include <time.h> 

#define CLOCKID CLOCK_REALTIME 
#define SIG SIGUSR1 

#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ 
          } while (0) 

unsigned char OUT[32]; 
unsigned char IN[32]; 

unsigned char ascii2hex(char in){ 

unsigned char out; 

    if(('0' <= in) && (in <= '9')) 
     out = in - '0'; 
    if(('A' <= in) && (in <= 'F')) 
     out = in - 'A' + 10; 
    if(('a' <= in) && (in <= 'f')) 
     out = in - 'a' + 10; 

    return out; 
} 

void asciiStr2hex(char * in, unsigned char * out, unsigned int len){ 

int i = 0; 
int j = 0; 
for(i = 0; i < len; i+=2){ 
     out[j++] = (ascii2hex(in[i ]) << 4) + ascii2hex(in[i+1]); 
    } 
} 

void testcode(unsigned char *out, unsigned char *in, unsigned int len){ 
unsigned int i; 
for (i=0;i<len;i++) 
    out[i] = in[i]; 
} 

static void print_siginfo(siginfo_t *si) 
{ 
    timer_t *tidp; 
    int or; 

    tidp = si->si_value.sival_ptr; 

    printf(" sival_ptr = %p; ", si->si_value.sival_ptr); 
    printf(" *sival_ptr = 0x%lx\n", (long) *tidp); 

    or = timer_getoverrun(*tidp); 
    if (or == -1) 
     errExit("timer_getoverrun"); 
    else 
     printf(" overrun count = %d\n", or); 
    } 

static void handler(int sig, siginfo_t *si, void *uc) 
{ 
    /* Note: calling printf() from a signal handler is not 
     strictly correct, since printf() is not async-signal-safe; 
     see signal(7) */ 

    printf("Caught signal %d\n", sig); 
    print_siginfo(si); 
    signal(sig, SIG_IGN); 
} 

int main(int argc, char *argv[]) 
{ 
    timer_t timerid; 
    struct sigevent sev; 
    struct itimerspec its; 
    long long freq_nanosecs; 
    //sigset_t mask; 
    struct sigaction sa; 

    if (argc != 3) { 
     fprintf(stderr, "Usage: %s <16byte> <time-nanosecs>\n", 
       argv[0]); 
     exit(EXIT_FAILURE); 
    } 

    asciiStr2hex(argv[1], IN, 32); 

    /* Establish handler for timer signal */ 

    printf("Establishing handler for signal %d\n", SIG); 
    sa.sa_flags = SA_SIGINFO; 
    sa.sa_sigaction = handler; 
    sigemptyset(&sa.sa_mask); 
    if (sigaction(SIG, &sa, NULL) == -1) 
     errExit("sigaction"); 

    /* Block timer signal temporarily */ 

/*  printf("Blocking signal %d\n", SIG); 
     sigemptyset(&mask); 
     sigaddset(&mask, SIG); 
     if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) 
      errExit("sigprocmask"); 
*/ 
     /* Create the timer */ 

    sev.sigev_notify = SIGEV_SIGNAL; 
    sev.sigev_signo = SIG; 
    sev.sigev_value.sival_ptr = &timerid; 
    if (timer_create(CLOCKID, &sev, &timerid) == -1) 
     errExit("timer_create"); 

    printf("timer ID is 0x%lx\n", (long) timerid); 

    /* Start the timer */ 

    freq_nanosecs = atoll(argv[2]); 
    its.it_value.tv_sec = freq_nanosecs/1000000000; 
    its.it_value.tv_nsec = freq_nanosecs % 1000000000; 
    its.it_interval.tv_sec = its.it_value.tv_sec; 
    its.it_interval.tv_nsec = its.it_value.tv_nsec; 

    if (timer_settime(timerid, 0, &its, NULL) == -1) 
     errExit("timer_settime"); 

    /* Sleep for a while; meanwhile, the timer may expire 
     multiple times */ 

    printf("Sleeping for %d seconds\n", atoi(argv[1])); 

    testcode(OUT, IN, 16); 


    /* Unlock the timer signal, so that timer notification 
     can be delivered */ 

    /* printf("Unblocking signal %d\n", SIG); 
     if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) 
      errExit("sigprocmask"); 
    */ 
    exit(EXIT_SUCCESS); 
} 

R 00112233445566778899001122334455 2 とGDBにデバッグするとき、私は得る:

Program received signal SIGUSR1, User defined signal 1. 
0x76fc7c38 in timer_settime() from /lib/arm-linux-gnueabihf/librt.so.1 
(gdb) x/30i $pc 
=> 0x76fc7c38 <timer_settime+16>: cmn r0, #4096 ; 0x1000 
0x76fc7c3c <timer_settime+20>: mov r4, r0 
0x76fc7c40 <timer_settime+24>: bhi 0x76fc7c4c <timer_settime+36> 
0x76fc7c44 <timer_settime+28>: mov r0, r4 
0x76fc7c48 <timer_settime+32>: pop {r3, r4, r7, pc} 
0x76fc7c4c <timer_settime+36>: bl 0x76fc55b4 
0x76fc7c50 <timer_settime+40>: rsb r3, r4, #0 
0x76fc7c54 <timer_settime+44>: mvn r4, #0 
0x76fc7c58 <timer_settime+48>: str r3, [r0] 
0x76fc7c5c <timer_settime+52>: b 0x76fc7c44 <timer_settime+28> 
0x76fc7c60 <timer_settime+56>: andeq r0, r0, r2, lsl #2 
0x76fc7c64: push {r4, r5, r6, r7, r8, r9, r10, lr} 
0x76fc7c68: sub sp, sp, #600 ; 0x258 
0x76fc7c6c: ldr r4, [pc, #340] ; 0x76fc7dc8 
0x76fc7c70: add r1, sp, #512 ; 0x200 
0x76fc7c74: add r4, pc, r4 
0x76fc7c78: mov r0, r4 
0x76fc7c7c: bl 0x76fc56b0 
0x76fc7c80: cmp r0, #0 
0x76fc7c84: bne 0x76fc7c98 
0x76fc7c88: ldr r2, [sp, #512] ; 0x200 
0x76fc7c8c: ldr r3, [pc, #312] ; 0x76fc7dcc 
0x76fc7c90: cmp r2, r3 
0x76fc7c94: beq 0x76fc7d94 
0x76fc7c98: ldr r5, [pc, #304] ; 0x76fc7dd0 
0x76fc7c9c: ldr r0, [pc, #304] ; 0x76fc7dd4 
0x76fc7ca0: add r5, pc, r5 
0x76fc7ca4: add r0, pc, r0 
0x76fc7ca8: mov r1, r5 
0x76fc7cac: bl 0x76fc5524 

私はラズベリーパイのようなコードを実行していますが、私が持っていたI'amはかなり確信して別のLinuxマシンx86_64で同じ動作。 私は "handle stop SIGUSR1"でテストしました。

+0

おそらく、ブレークポイントは、デバッグが安全であることを示すポイントに設定されている可能性があります。それ以前は、ハウスキーピングが行われました(レジスタの保存、スタックフレームの設定など)。 –

+0

前の説明は何ですか? – Art

+0

dbgからのシグナルを傍受するために使用されるメカニズムは、私にはあまりあいまいです。私はgdbが子供に渡される前にすべてのシグナルを単に傍受できると思っていました。だから私は本当のブレークポイントがないと思った。ちょうどgdbがシグナルを保持している限り、子供は続行を許されない。 シグナルリングとそれが実行を停止したときにブレークポイントが設定されることをお勧めしますか? – user5162288

答えて

0

最終的に私が期待していた動作を得るためには、gdbのset unwindonsignal offに問題があることがわかりました。

関連する問題