Dies ist eine Fortsetzung des vorherigen Trace-Benutzerprogramms mit SystemTap Teil 1.
Das letzte Mal war der Zweck "Sehen wir uns die Bewegung an, ohne die vorhandene Quelle zu ändern". Dieses Mal werde ich beschreiben, wie SystemTap zum Zweck verwendet wird: "Wenn Sie Ihr eigenes Programm entwickeln, lassen Sie uns verfolgen, während Sie den variablen Wert des Sonderziels als Debugging-Tool ausgeben."
Die folgenden Funktionen wurden im vorherigen Trace-Skript realisiert. ・ Einrücken um die Tiefe der Funktion -Liste der Funktionsargumente und ihrer Werte
Darüber hinaus wollte ich, dass die folgende Ausgabe dem Verhalten meines eigenen Programms folgt. ・ Ich möchte wissen, wo ich vorbeigekommen bin, als es einen Zweig in der Funktion gab. ・ Ich möchte den Wert der interessierenden Variablen wissen.
Ich konnte es schaffen. Es gibt Stellen, an denen es möglich erscheint, eine komplexere Methode zu entwickeln, aber ich werde sie an dieser Stelle als Methode veröffentlichen.
Das Implementierungsverfahren wird beschrieben. SystemTap-Skripte und ihre entsprechenden Header-Dateien für C ++, Zeigt die Ausführungsmethode und das Ausführungsergebnis des C ++ - Quellcodes SystemTap an.
Angenommen, Sie haben die folgenden drei Dateien "tr2.cpp", "ttr3.stp" und "ttr3.h" im Verzeichnis / home / TestProgs / tr1 /.
/home/TestProgs/tr2/ttr3.stp
#!/usr/bin/stap
probe $1.begin
{
printf("[proc begin] pid=%d,procname=%s\n",
pid(), //Prozessnummer
execname() //Name der Ausführungsdatei
);
}
probe $1.end
{
printf("[proc end] pid=%d,procname=%s\n", pid(), execname());
}
//Probe zum Systemaufruf
probe $1.syscall
{
# open systemcall
if( $syscall == 2) {
printf("%s open(%s)\n",thread_indent(0),kernel_string($arg1))
}
# close systemcall
else if ( $syscall == 3) {
printf("%s close(%d)\n",thread_indent(0), $arg1)
}
//Systemrufnummer ist"ausyscall --dump"Es kann mit dem Befehl von erhalten werden.
}
//Sonde zum Start der Funktion
probe $1.function("*").call
{
printf("%s-->%s(%s) @%s %s\n",
thread_indent(0),
ppfunc(), //Funktionsname(Klassenname und Namespace werden nicht angezeigt.
$$parms, //Argumentliste
usymfileline(addr()), //Dateiname und Zeilennummer
probefunc() //Funktionsname(Nicht entwirrt)
);
thread_indent(1); //
}
//Sonde bis zum Ende der Funktion
probe $1.function("*").return
{
thread_indent(-1);
printf("%s<--%s,%s\n",
thread_indent(0),
ppfunc(),
$$return //Rückgabewert
);
}
//define TR_FUNC() STAP_PROBE2(myTrace,lineFunc,__LINE__,__PRETTY_FUNCTION__)
probe $1.provider("myTrace").mark("lineFunc")
{
printf("%s%s:%d:%s\n",
thread_indent(0),
usymfile(addr()), //Name der Quellcodedatei
$arg1, // __LINE__
user_string($arg2) //User Space String__PRETTY_FUNCTION__
);
}
//define TR_LINE() STAP_PROBE1(myTrace,line,__LINE__)
probe $1.provider("myTrace").mark("line")
{
printf("%s L:%d\n",
thread_indent(0),
$arg1 // __LINE__
);
}
//define TR_LINE_MSG(a1) STAP_PROBE2(myTrace,lineMsg,__LINE__,a1)
probe $1.provider("myTrace").mark("lineMsg")
{
printf("%s L:%d, %s",
thread_indent(0),
$arg1, // __LINE__
user_string($arg2)
);
}
//define TR_MSG(a1) STAP_PROBE1(myTrace,msg,a1)
probe $1.provider("myTrace").mark("msg")
{
printf("%s",
user_string($arg1)
);
}
//define TR_d(a1) STAP_PROBE2(myTrace,p_d,#a1,a1)
probe $1.provider("myTrace").mark("p_d")
{
printf("%s=%d ",
user_string($arg1),
$arg2
);
}
//define TR_u(a1) STAP_PROBE2(myTrace,p_u,#a1,a1)
probe $1.provider("myTrace").mark("p_u")
{
printf("%s=%u ",
user_string($arg1),
$arg2
);
}
//define TR_x(a1) STAP_PROBE2(myTrace,p_x,#a1,a1)
probe $1.provider("myTrace").mark("p_x")
{
printf("%s=0x%x ",
user_string($arg1),
$arg2
);
}
//define TR_s(a1) STAP_PROBE2(myTrace,p_s,#a1,a1)
probe $1.provider("myTrace").mark("p_s")
{
printf("%s='%s' ",
user_string($arg1),
user_string($arg2)
);
}
//define TR_LOCAL() STAP_PROBE(myTrace,local);
probe $1.provider("myTrace").mark("local")
{
printf("[$$locals] %s\n",$$locals); //Alle lokalen Variablen im Gültigkeitsbereich
}
Wir haben provider (). Mark () verwendet, um den Quellcode zu prüfen. -Die von povider () angegebene Zeichenfolge wird als Namespace und die von mark () angegebene Zeichenfolge als Identifikationsname verwendet.
/home/TestProgs/tr2/ttr3.h
#ifndef __TTR3_MYTRACE_H_
#define __TTR3_MYTRACE_H_ 1
#ifndef NO_MYTRACE
#include <stdio.h>
#include <sys/sdt.h>
//Einzug+Name der Quelldatei+Zeilennummer+Demangled Funktionsname+Neue Zeile
#define TR_FUNC() STAP_PROBE2(myTrace,lineFunc,__LINE__,__PRETTY_FUNCTION__)
//Einzug+Zeilennummer+Neue Zeile
#define TR_LINE() STAP_PROBE1(myTrace,line,__LINE__)
//Einzug+Zeilennummer+Argumentzeichenfolge
#define TR_LINE_MSG(a1) STAP_PROBE2(myTrace,lineMsg,__LINE__,a1)
//Argumentzeichenfolge
#define TR_MSG(a1) STAP_PROBE1(myTrace,msg,a1)
//Variablenname und sein Wert(printf%d Format)
#define TR_d(a1) STAP_PROBE2(myTrace,p_d,#a1,a1)
//Variablenname und sein Wert(printf%u Format)
#define TR_u(a1) STAP_PROBE2(myTrace,p_u,#a1,a1)
//Variablenname und sein Wert(printf%x-Format)
#define TR_x(a1) STAP_PROBE2(myTrace,p_x,#a1,a1)
//Variablenname und sein Wert(printf%s Format)
#define TR_s(a1) STAP_PROBE2(myTrace,p_s,#a1,a1)
//Variablennamen und ihre Werte für alle lokalen Variablen im Gültigkeitsbereich+Neue Zeile
#define TR_LOCAL() STAP_PROBE(myTrace,local);
//Dummy-Testfunktion
// "> stap -v ttr3.stp "Wann, ttr3.mark in stp definiert()Wenn es jedoch nicht einmal im CPP-Code erscheint, führt die Stap-Ausführung zu einem Fehler.
//Dient auch als Testcode ttr3.Marke definiert durch stap()All dies wird in dieser Funktion beschrieben.
void STAP_TRACE_defines(){
int dmyI=0;
const char *dmyS="dummy";
TR_FUNC();
TR_LINE();
TR_LINE_MSG("test mesg\n");
TR_MSG("test mesg\n");
TR_d(dmyI);
TR_u(dmyI);
TR_x(dmyI);
TR_s(dmyS);
TR_LOCAL();
printf("%s %d\n",dmyS,dmyI);
}
#else
#define TR_FUNC() /**/
#define TR_LINE() /**/
#define TR_LINE_MSG(a1) /**/
#define TR_MSG(a1) /**/
#define TR_d(a1) /**/
#define TR_u(a1) /**/
#define TR_x(a1) /**/
#define TR_s(a1) /**/
#define TR_LOCAL() /**/
#endif // NO_MYTRACE
#endif // __TTR3_MYTRACE_H_
/home/TestProgs/tr2/tr2.cpp
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <assert.h>
#include "ttr3.h"
class classSample1{
public:
classSample1(){};
~classSample1(){};
int func_C1(){
printf("classSample1::func_C1()\n");
TR_LINE(); //Zeilenumbruch der eingerückten Zeilennummer
return 0;
}
int func_C2(int m);
int cnt_func_C2 = 0;
};
int classSample1::func_C2(int m){
printf("classSample2::func_C2()\n");
TR_FUNC(); //Einrückungsdateiname Zeilennummer entwirrter Funktionsname Zeilenumbruch
cnt_func_C2++;
int l= cnt_func_C2 % 2;
uint32_t u32=0xfffffffd + cnt_func_C2;
uint64_t u64=0xfffffffffffffffd + cnt_func_C2;
int32_t i32=-3 + cnt_func_C2;
int64_t i64=-3 + cnt_func_C2;
printf("cnt_func_C2 %d , l:%d ,u32:%u, u64:%lu\n",cnt_func_C2,l,u32,u64);
TR_LINE_MSG("");TR_d(cnt_func_C2);TR_d(l);TR_MSG("\n"); //Einrückungszeilennummer cnt_func_C2-Wert l-Wert Zeilenvorschub
TR_LINE_MSG("");TR_d(i32);TR_u(u32);TR_d(i64);TR_u(u64);TR_MSG("\n"); //Einrückungszeilennummer i32-Wert u32-Wert i64-Wert u64-Wert Zeilenvorschub
TR_LINE_MSG("");TR_LOCAL(); //Einzug Alle lokalen Variablen in diesem Bereich()
assert(cnt_func_C2<m); //Als Beispiel ausgesetzt.
if (l == 0) {
TR_LINE_MSG("even.\n"); //Zeichenfolge für eingerückte Zeilennummer
return 0;
}else{
TR_LINE_MSG("odd.\n"); //Zeichenfolge für eingerückte Zeilennummer
return 1;
}
}
int main(int argc, char *argv[])
{
int ret=0;
classSample1 c1;
for(;;) {
ret = c1.func_C1();
sleep(2);
ret = c1.func_C2(5);
sleep(2);
}
return ret;
}
-TR _ *** wird wie printf hinzugefügt.
> cd /home/TestProgs/tr2/
> gcc -Wall -g -O0 -std=c++11 tr2.cpp -o tr2 -lstdc++
> stap -v ttr3.stp 'process("/home/TestProgs/tr2/tr2")'
Geben Sie dem Argument eine Zeichenfolge, die den vollständigen Pfad zur ausführbaren Datei enthält. Das unten gezeigte Parser-Ergebnis wird ausgegeben.
stdout
Pass 1: parsed user script and 491 library scripts using 243904virt/56396res/3316shr/53796data kb, in 790usr/40sys/837real ms.
WARNING: function _start return probe is blacklisted: keyword at ttr3.stp:45:1
source: probe $1.function("*").return
^
Pass 2: analyzed script: 57 probes, 41 functions, 6 embeds, 2 globals using 246812virt/60696res/4680shr/56704data kb, in 120usr/110sys/228real ms.
Pass 3: translated to C into "/tmp/stap4b9QpY/stap_8a82d56cba8247f5ae53b508cd7dbe33_50483_src.c" using 246956virt/61192res/5028shr/56848data kb, in 50usr/110sys/159real ms.
Pass 4: compiled C into "stap_8a82d56cba8247f5ae53b508cd7dbe33_50483.ko" in 4050usr/640sys/4517real ms.
Pass 5: starting run.
> cd /home/TestProgs/tr2/
> ./tr2
stdout
[proc begin] pid=16890,procname=tr2
0 tr2(16890): open(/etc/ld.so.cache)
0 tr2(16890): close(3)
0 tr2(16890): open(/lib64/libstdc++.so.6)
0 tr2(16890): close(3)
0 tr2(16890): open(/lib64/libgcc_s.so.1)
0 tr2(16890): close(3)
0 tr2(16890): open(/lib64/libc.so.6)
0 tr2(16890): close(3)
0 tr2(16890): open(/lib64/libm.so.6)
0 tr2(16890): close(3)
0 tr2(16890):-->_start() @0x4006e0 _start
19 tr2(16890):-->__libc_csu_init() @0x400a10 __libc_csu_init
32 tr2(16890): -->_init() @0x400628 _init
43 tr2(16890): <--_init,
47 tr2(16890): -->frame_dummy() @0x4007a0 frame_dummy
57 tr2(16890): -->register_tm_clones() @0x400740 register_tm_clones
68 tr2(16890): <--register_tm_clones,
70 tr2(16890): <--frame_dummy,
73 tr2(16890):<--__libc_csu_init,
86 tr2(16890):-->main(argc=0x1 argv=0x7ffc0ea27058) @/home/TestProgs/tr2/tr2.cpp:53 main
100 tr2(16890): -->classSample1(this=0x0) @/home/TestProgs/tr2/tr2.cpp:11 _ZN12classSample1C2Ev
113 tr2(16890): <--classSample1,
116 tr2(16890): -->func_C1(this=0x7ffc0ea26f50) @/home/TestProgs/tr2/tr2.cpp:13 _ZN12classSample17func_C1Ev
222 tr2(16890): L:15
227 tr2(16890): <--func_C1,return=0x0
2003172 tr2(16890): -->func_C2(this=0x7ffc0ea26f50 m=0x5) @/home/TestProgs/tr2/tr2.cpp:23 _ZN12classSample17func_C2Ei
2003220 tr2(16890): /home/TestProgs/tr2/tr2.cpp:24:int classSample1::func_C2(int)
2003281 tr2(16890): L:34, cnt_func_C2=1 l=1
2003299 tr2(16890): L:35, i32=-2 u32=4294967294 i64=-2 u64=18446744073709551614
2003324 tr2(16890): L:36, [$$locals] __PRETTY_FUNCTION__=[...] l=0x1 u32=0xfffffffe u64=0xfffffffffffffffe i32=0xfffffffffffffffe i64=0xfffffffffffffffe
2003337 tr2(16890): L:44, odd.
2003345 tr2(16890): <--func_C2,return=0x1
4003668 tr2(16890): -->func_C1(this=0x4006e0) @/home/TestProgs/tr2/tr2.cpp:13 _ZN12classSample17func_C1Ev
4003729 tr2(16890): L:15
4003738 tr2(16890): <--func_C1,return=0x0
6006538 tr2(16890): -->func_C2(this=0x7ffc0ea26f50 m=0x5) @/home/TestProgs/tr2/tr2.cpp:23 _ZN12classSample17func_C2Ei
6006587 tr2(16890): /home/TestProgs/tr2/tr2.cpp:24:int classSample1::func_C2(int)
6006612 tr2(16890): L:34, cnt_func_C2=2 l=0
6006630 tr2(16890): L:35, i32=-1 u32=4294967295 i64=-1 u64=18446744073709551615
6006655 tr2(16890): L:36, [$$locals] __PRETTY_FUNCTION__=[...] l=0x0 u32=0xffffffff u64=0xffffffffffffffff i32=0xffffffffffffffff i64=0xffffffffffffffff
6006668 tr2(16890): L:41, even.
6006676 tr2(16890): <--func_C2,return=0x0
8008347 tr2(16890): -->func_C1(this=0x4006e0) @/home/TestProgs/tr2/tr2.cpp:13 _ZN12classSample17func_C1Ev
8008409 tr2(16890): L:15
8008418 tr2(16890): <--func_C1,return=0x0
10009956 tr2(16890): -->func_C2(this=0x7ffc0ea26f50 m=0x5) @/home/TestProgs/tr2/tr2.cpp:23 _ZN12classSample17func_C2Ei
10010004 tr2(16890): /home/TestProgs/tr2/tr2.cpp:24:int classSample1::func_C2(int)
10010028 tr2(16890): L:34, cnt_func_C2=3 l=1
10010046 tr2(16890): L:35, i32=0 u32=0 i64=0 u64=0
10010070 tr2(16890): L:36, [$$locals] __PRETTY_FUNCTION__=[...] l=0x1 u32=0x0 u64=0x0 i32=0x0 i64=0x0
10010081 tr2(16890): L:44, odd.
10010089 tr2(16890): <--func_C2,return=0x1
12014178 tr2(16890): -->func_C1(this=0x4006e0) @/home/TestProgs/tr2/tr2.cpp:13 _ZN12classSample17func_C1Ev
12014238 tr2(16890): L:15
12014246 tr2(16890): <--func_C1,return=0x0
14014842 tr2(16890): -->func_C2(this=0x7ffc0ea26f50 m=0x5) @/home/TestProgs/tr2/tr2.cpp:23 _ZN12classSample17func_C2Ei
14014888 tr2(16890): /home/TestProgs/tr2/tr2.cpp:24:int classSample1::func_C2(int)
14014912 tr2(16890): L:34, cnt_func_C2=4 l=0
14014930 tr2(16890): L:35, i32=1 u32=1 i64=1 u64=1
14014953 tr2(16890): L:36, [$$locals] __PRETTY_FUNCTION__=[...] l=0x0 u32=0x1 u64=0x1 i32=0x1 i64=0x1
14014965 tr2(16890): L:41, even.
14014972 tr2(16890): <--func_C2,return=0x0
16015484 tr2(16890): -->func_C1(this=0x4006e0) @/home/TestProgs/tr2/tr2.cpp:13 _ZN12classSample17func_C1Ev
16015579 tr2(16890): L:15
16015588 tr2(16890): <--func_C1,return=0x0
18020986 tr2(16890): -->func_C2(this=0x7ffc0ea26f50 m=0x5) @/home/TestProgs/tr2/tr2.cpp:23 _ZN12classSample17func_C2Ei
18021033 tr2(16890): /home/TestProgs/tr2/tr2.cpp:24:int classSample1::func_C2(int)
18021057 tr2(16890): L:34, cnt_func_C2=5 l=1
18021074 tr2(16890): L:35, i32=2 u32=2 i64=2 u64=2
18021098 tr2(16890): L:36, [$$locals] __PRETTY_FUNCTION__=[...] l=0x1 u32=0x2 u64=0x2 i32=0x2 i64=0x2
[proc end] pid=16890,procname=tr2
Von der vorherigen Funktion, ・ Einrücken um die Tiefe der Funktion -Liste der Funktionsargumente und ihrer Werte
Recommended Posts