List of commits:
Subject Hash Author Date (UTC)
Lots of updates 5583e8dbd607b684a14ced92b4d2ffdacbcf57e1 Catalin(ux) M. BOIE 2022-11-18 05:40:05
mysql, sqlite3, depth d9d83cafbd372d1055fa2e51cdf3deb2396f5d08 Catalin(ux) M. BOIE 2022-11-07 05:58:04
More spec fixes 3867b17137b5397c3eeabdcbbc232417ad212a27 Catalin(ux) M. BOIE 2022-10-25 19:04:28
More spec fixes 68abc4ce485fbbcc18a232e57b956f9e2b016d72 Catalin(ux) M. BOIE 2022-10-25 18:48:22
Fixed installation paths in Makefiles c98920bd55f7cd2ebcec7083e2360009d8c16b29 Catalin(ux) M. BOIE 2022-10-25 18:19:49
Debian support added, create correctly the paths for install 512c13ca06dda005504cdeab831431c943dde74a Catalin(ux) M. BOIE 2022-10-25 06:19:50
Bump version to 0.6 for a stupid reason (mass with dupdump) c4d10510ddf944965a80d9a3e5f4ac62b84a103e Catalin(ux) M. BOIE 2022-10-25 06:04:33
History update c83cd94af87636bc67bf9526ca0a65734ce96fac Catalin(ux) M. BOIE 2022-10-22 10:34:01
TODO update b1cbf0845dada017466763126d8569f62ace4cb4 Catalin(ux) M. BOIE 2022-10-22 08:20:20
Need libcap 4cdcd084fcf0e089e074aa0b090bc6f569a5d625 Catalin(ux) M. BOIE 2022-10-22 07:32:51
Removed BuildArch 54a76d595eb787edbd887d567eb5b29a6261cb4a Catalin(ux) M. BOIE 2022-10-21 18:51:41
Add 'catalinux+' for Conn d7b41a60e091fdd10aee5b45355c07896155853b Catalin(ux) M. BOIE 2022-10-21 18:39:11
We need Conn library d7412ea414a52fb289d70cc309dee8ceb5c5a67e Catalin(ux) M. BOIE 2022-10-21 16:12:03
spec: require gnutls and json-c f6378fc9cb10a110ae9d6826de0784de41ba4f72 Catalin(ux) M. BOIE 2022-10-21 15:20:07
More 'stat' related changes a94da02a9867f5a93d6d2098caf62b39541e36f1 Catalin(ux) M. BOIE 2022-10-21 14:56:48
Really first version (all files added) 0cf2be651bd2a2f93fe0af1c4bd56a11910791c5 Catalin(ux) M. BOIE 2022-10-21 12:48:38
First version d2839681f34f4760ac29dab2c6fa3f52544ed5af Catalin(ux) M. BOIE 2022-10-21 12:26:32
gnutls working, more js stuff cea2625f1129f2e6decb4947c18be31adedfe9e5 Catalin(ux) M. BOIE 2022-09-26 16:44:19
First add d3b73b065b617424162195b5dfef2f0121adaa46 Catalin(ux) M. BOIE 2022-07-08 05:54:34
Commit 5583e8dbd607b684a14ced92b4d2ffdacbcf57e1 - Lots of updates
Author: Catalin(ux) M. BOIE
Author date (UTC): 2022-11-18 05:40
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2022-11-18 05:40
Parent(s): d9d83cafbd372d1055fa2e51cdf3deb2396f5d08
Signer:
Signing key:
Signing status: N
Tree: 2d32d41a303253364defb0a1ce46f27463f4155e
File Lines added Lines deleted
agent/java/agent/Makefile 6 3
agent/java/agent/MyInstrumentationAgent.java 69 59
agent/java/agent/QueryTransformer.java 25 25
agent/ninedogs.TODO 5 1
agent/ninedogs.c 477 72
agent/php.c 321 29
agent/process_db.c 36 8
agent/process_db.h 44 7
agent/python.c 13 15
common/ids.h 8 0
docs/.gitignore 6 0
docs/Makefile 5 0
docs/pre1.tex 232 0
docs/pre1.txt 3 0
test/dotnet/a1/1.run 6 5
test/dotnet/a1/Program.cs 1 1
test/java/jdbc/1.run 5 1
test/java/jdbc/pg1.java 14 11
test/php-dns/1.php 6 0
test/php-dns/1.run 2 2
test/php-mysql/1.php 33 4
test/php-mysql/1.run 1 1
test/php-pg/1.run 2 2
test/php-pg/free-result.sh 2 1
test/php-sock/3.run 3 3
test/python/sqlite1.py 9 4
test/segv1/1.run 3 2
test/segv1/segv.c 2 0
trace/TODO 1 2
trace/nd-trace.c 340 46
File agent/java/agent/Makefile changed (mode: 100644) (index fac3b4a..b218671)
1
2 1 CLASSES := AtmTransformer.class QueryTransformer.class MyInstrumentationAgent.class CLASSES := AtmTransformer.class QueryTransformer.class MyInstrumentationAgent.class
3 2 JARS := javassist.jar ninedogs.jar JARS := javassist.jar ninedogs.jar
4 3
5 ninedogs-agent.jar: Makefile META-INF/MANIFEST.MF $(JARS) $(CLASSES)
4 ninedogs-agent.jar: Makefile META-INF/MANIFEST.MF ninedogs.jar $(CLASSES)
6 5 jar --create --verbose --manifest META-INF/MANIFEST.MF \ jar --create --verbose --manifest META-INF/MANIFEST.MF \
7 --file ninedogs-agent.jar $(JARS) $(CLASSES)
6 --file ninedogs-agent.jar ninedogs.jar $(CLASSES)
8 7 @sleep .3 @sleep .3
9 8
10 9 ninedogs.jar: Makefile META-INF/MANIFEST.MF ninedogs.class ninedogs.jar: Makefile META-INF/MANIFEST.MF ninedogs.class
 
... ... QueryTransformer.class: QueryTransformer.java
24 23 MyInstrumentationAgent.class: MyInstrumentationAgent.java MyInstrumentationAgent.class: MyInstrumentationAgent.java
25 24 javac -cp . MyInstrumentationAgent.java javac -cp . MyInstrumentationAgent.java
26 25
26 install: ninedogs-agent.jar
27 @mkdir -p $(if $(I_USR_SHARE), $(I_USR_SHARE), /usr/share)/ninedogs
28 @cp -v $(JARS) $(if $(I_USR_SHARE), $(I_USR_SHARE), /usr/share)/ninedogs/
29
File agent/java/agent/MyInstrumentationAgent.java changed (mode: 100644) (index 8818f7d..c90a2c2)
... ... import java.lang.instrument.Instrumentation;
4 4
5 5 public class MyInstrumentationAgent public class MyInstrumentationAgent
6 6 { {
7 public static void premain(String agentArgs, Instrumentation inst)
7 private static void transform(Class<?> clazz, ClassLoader classLoader, Instrumentation instrumentation)
8 8 { {
9 System.err.println("MyInstrumentationAgent.Premain...");
10
11 if (1 == 0) {
12 // This crashes badly
13 // Transform all classes
14 for (Class<?> clazz: inst.getAllLoadedClasses()) {
15 //System.err.println(" iter " + clazz.getName());
16 transformClass(clazz.getName(), inst);
17 }
18 } else {
19 transformClass("org.postgresql.Driver", inst);
20 transformClass("org.postgresql.jdbc.PgPreparedStatement", inst);
21 transformClass("org.postgresql.jdbc.PgResultSet", inst);
22 transformClass("org.postgresql.jdbc.PgConnection", inst);
23 transformClass("org.postgresql.jdbc.PgStatement", inst);
24
25 transformClass("java.net.http.HttpClient", inst);
9 String n = clazz.getName();
26 10
27 //transformClass("sun.security.ssl.X509TrustManager", inst); // not working
28 //transformClass("javax.net.ssl", inst); // not working
11 //System.err.println("MyInstrumentationAgent.transform: clazz.getName()=" + n + " classLoader=" + classLoader);
29 12
30 transformClass("sun.security.ssl.X509TrustManagerImpl", inst);
31 transformClass("java.security.cert.X509Certificate", inst);
32 transformClass("java.security.cert.Certificate", inst);
33 transformClass("java.security.cert.CertificateFactory", inst);
34 //transformClass("javax.net.ssl.SSLContext", inst);
35 transformClass("java.io.File", inst);
36 //transformClass("java.io.InputStream", inst);
37 //transformClass("java.io.Reader", inst);
38 //transformClass("java.io.DataInputStream", inst);
39 //transformClass("java.io.FileInputStream", inst);
40 //transformClass("java.io.ByteArrayInputStream", inst);
13 //if (n.equals("org.postgresql.Driver")) {
14 // AtmTransformer dt = new AtmTransformer(n, classLoader);
15 // instrumentation.addTransformer(dt, true);
16 //} else if (n.equals("org.postgresql.jdbc.PgPreparedStatement")) {
17 // QueryTransformer dt = new QueryTransformer(n, classLoader);
18 // instrumentation.addTransformer(dt, true);
19 //if (n.equals("sun.security.ssl.X509TrustManagerImpl")) {
20 QueryTransformer qt = new QueryTransformer(n, classLoader);
21 instrumentation.addTransformer(qt, true); // true = can retransform
22 //} else {
23 // return;
24 //}
41 25
42 transformClass("javax.net.ssl.X509TrustManager", inst);
43 transformClass("javax.net.ssl.X509KeyManager", inst);
44 transformClass("sun.security.provider.X509Factory", inst);
45 transformClass("sun.security.x509.X509CertImpl", inst);
46 transformClass("sun.security.x509.X509CertInfo", inst);
26 try {
27 instrumentation.retransformClasses(clazz);
28 } catch (Exception ex) {
29 System.err.println(" transform: fail: " + ex);
30 // TODO: next line was un-commented
31 ///throw new RuntimeException(" Transform failed for class: [" + n + "]", ex);
47 32 } }
48
49 System.err.println("Premain finish...");
50 33 } }
51 34
52 35 private static void transformClass(String className, Instrumentation instrumentation) private static void transformClass(String className, Instrumentation instrumentation)
 
... ... public class MyInstrumentationAgent
71 54
72 55 //System.err.println(" iterating all classes..."); //System.err.println(" iterating all classes...");
73 56 // otherwise iterate all loaded classes and find what we want // otherwise iterate all loaded classes and find what we want
57
74 58 for (Class<?> clazz: instrumentation.getAllLoadedClasses()) { for (Class<?> clazz: instrumentation.getAllLoadedClasses()) {
75 59 //System.err.println(" comparing with " + clazz.getName()); //System.err.println(" comparing with " + clazz.getName());
76 60 if (clazz.getName().equals(className)) { if (clazz.getName().equals(className)) {
 
... ... public class MyInstrumentationAgent
85 69 //throw new RuntimeException("Failed to find class [" + className + "]"); //throw new RuntimeException("Failed to find class [" + className + "]");
86 70 } }
87 71
88 private static void transform(Class<?> clazz, ClassLoader classLoader, Instrumentation instrumentation)
72 public static void premain(String agentArgs, Instrumentation inst)
89 73 { {
90 String n = clazz.getName();
74 System.err.println("MyInstrumentationAgent.Premain...");
91 75
92 //System.err.println("MyInstrumentationAgent.transform: clazz.getName()=" + n + " classLoader=" + classLoader);
76 if (1 == 0) {
77 // This crashes badly
78 // Transform all classes
79 for (Class<?> clazz: inst.getAllLoadedClasses()) {
80 //System.err.println(" iter " + clazz.getName());
81 transformClass(clazz.getName(), inst);
82 }
83 } else {
84 // This generates Exception in thread "main" java.lang.ClassCircularityError: java/lang/WeakPairMap$Pair$Weak
85 //transformClass("org.postgresql.Driver", inst);
86 transformClass("org.postgresql.jdbc.PgPreparedStatement", inst);
87 transformClass("org.postgresql.jdbc.PgResultSet", inst);
88 transformClass("org.postgresql.jdbc.PgConnection", inst);
89 transformClass("org.postgresql.jdbc.PgStatement", inst);
93 90
94 //if (n.equals("org.postgresql.Driver")) {
95 // AtmTransformer dt = new AtmTransformer(n, classLoader);
96 // instrumentation.addTransformer(dt, true);
97 //} else if (n.equals("org.postgresql.jdbc.PgPreparedStatement")) {
98 // QueryTransformer dt = new QueryTransformer(n, classLoader);
99 // instrumentation.addTransformer(dt, true);
100 //if (n.equals("sun.security.ssl.X509TrustManagerImpl")) {
101 QueryTransformer qt = new QueryTransformer(n, classLoader);
102 instrumentation.addTransformer(qt, true);
103 //} else {
104 // return;
105 //}
91 if (1 == 0) {
92 transformClass("java.net.http.HttpClient", inst);
93 }
106 94
107 try {
108 instrumentation.retransformClasses(clazz);
109 } catch (Exception ex) {
110 System.err.println(" transform: fail: " + ex);
111 // TODO: next line was un-commented
112 ///throw new RuntimeException(" Transform failed for class: [" + n + "]", ex);
95 //transformClass("sun.security.ssl.X509TrustManager", inst); // not working
96 //transformClass("javax.net.ssl", inst); // not working
97
98 if (1 == 0) {
99 transformClass("sun.security.ssl.X509TrustManagerImpl", inst);
100 transformClass("java.security.cert.X509Certificate", inst);
101 transformClass("java.security.cert.Certificate", inst);
102 transformClass("java.security.cert.CertificateFactory", inst);
103 }
104
105 //transformClass("javax.net.ssl.SSLContext", inst);
106
107 ///transformClass("java.io.File", inst); // working
108 //transformClass("java.io.InputStream", inst);
109 //transformClass("java.io.Reader", inst);
110 //transformClass("java.io.DataInputStream", inst);
111 //transformClass("java.io.FileInputStream", inst);
112 //transformClass("java.io.ByteArrayInputStream", inst);
113
114 if (1 == 0) {
115 transformClass("javax.net.ssl.X509TrustManager", inst);
116 transformClass("javax.net.ssl.X509KeyManager", inst);
117 transformClass("sun.security.provider.X509Factory", inst);
118 transformClass("sun.security.x509.X509CertImpl", inst);
119 transformClass("sun.security.x509.X509CertInfo", inst);
120 }
113 121 } }
122
123 System.err.println("Premain finish...");
114 124 } }
115 125 } }
116 126
File agent/java/agent/QueryTransformer.java changed (mode: 100644) (index ad8e8aa..29ec08e)
... ... public class QueryTransformer implements ClassFileTransformer
64 64 //CtMethod m = cc.getDeclaredMethod(WITHDRAW_MONEY_METHOD); //CtMethod m = cc.getDeclaredMethod(WITHDRAW_MONEY_METHOD);
65 65 //System.err.println(" CtMethod: " + m); //System.err.println(" CtMethod: " + m);
66 66
67 //if (1 == 1) { // seems this crashes at some point
68 if (className.equals("java/io/File")) {
69 CtConstructor[] cons = cc.getDeclaredConstructors();
70 for (CtConstructor con : cons) {
71 StringBuilder sb = new StringBuilder();
72 StringBuilder eb = new StringBuilder();
73
74 String sig = con.getSignature();
75 System.err.println(" constructor: " + con + " sig=" + sig);
76 sb.append("ninedogs.log(\"constructor for class " + className + " " + sig + " this=\" + this + \" $0=\" + $0);");
77 eb.append("ninedogs.log(\" exit this: \" + this + \" $0=\" + $0);"); // seems 'this' is always null...
78
79 CtClass[] pTypes = con.getParameterTypes();
80 for (int i = 0; i < pTypes.length; i++)
81 sb.append("ninedogs.log(\" c-para[" + i + "] [" + pTypes[i].getName() + "]: \" + $args[" + i + "]);");
82
83 con.insertBefore("{" + sb.toString() + "}");
84 con.insertAfter("{" + eb.toString() + "}");
67 // seems this crashes at some point
68 if (className.equals("TODO java/io/File TODO")) {
69 CtConstructor[] cons = cc.getDeclaredConstructors();
70 for (CtConstructor con : cons) {
71 StringBuilder sb = new StringBuilder();
72 StringBuilder eb = new StringBuilder();
73
74 String sig = con.getSignature();
75 System.err.println(" constructor: " + con + " sig=" + sig);
76 sb.append("ninedogs.log(\"constructor for class " + className + " " + sig + " this=\" + this + \" $0=\" + $0);");
77 eb.append("ninedogs.log(\" exit this: \" + this + \" $0=\" + $0);"); // seems 'this' is always null...
78
79 CtClass[] pTypes = con.getParameterTypes();
80 for (int i = 0; i < pTypes.length; i++)
81 sb.append("ninedogs.log(\" c-para[" + i + "] [" + pTypes[i].getName() + "]: \" + $args[" + i + "]);");
82
83 con.insertBefore("{" + sb.toString() + "}");
84 con.insertAfter("{" + eb.toString() + "}");
85 }
85 86 } }
86 }
87 87
88 88 ///System.err.println(" Iterating methods..."); ///System.err.println(" Iterating methods...");
89 89 // Searchy for (Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection; // Searchy for (Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;
 
... ... public class QueryTransformer implements ClassFileTransformer
102 102
103 103 // This is heavy debug // This is heavy debug
104 104 //sb.append("System.err.println(\"method " + className + "." + m.getName() + " " + sig + "\");"); //sb.append("System.err.println(\"method " + className + "." + m.getName() + " " + sig + "\");");
105 sb.append("ninedogs.log(\"method " + className + "." + m.getName() + " " + sig + "\");");
106 eb.append("ninedogs.log(\" ret: \" + $_);");
105 ///sb.append("ninedogs.log(\"method " + className + "." + m.getName() + " " + sig + "\");");
106 ///eb.append("ninedogs.log(\" ret: \" + $_);");
107 107
108 108 if (className.equals("org/postgresql/Driver") if (className.equals("org/postgresql/Driver")
109 109 && m.getName().equals("connect") && m.getName().equals("connect")
 
... ... public class QueryTransformer implements ClassFileTransformer
155 155 //sb.append("sbArgs.append(System.identityHashCode( $0 ) );"); //sb.append("sbArgs.append(System.identityHashCode( $0 ) );");
156 156 */ */
157 157
158 CtClass[] pTypes = m.getParameterTypes();
159 for (int i = 0; i < pTypes.length; i++) {
158 //CtClass[] pTypes = m.getParameterTypes();
159 //for (int i = 0; i < pTypes.length; i++) {
160 160 //if ((i == 0) && (pTypes[i].toString() == "java.lang.String")) //if ((i == 0) && (pTypes[i].toString() == "java.lang.String"))
161 161 ///sb.append("ninedogs.log(\" para[" + i + "] [" + pTypes[i].getName() + "]: \" + $args[" + i + "]);"); ///sb.append("ninedogs.log(\" para[" + i + "] [" + pTypes[i].getName() + "]: \" + $args[" + i + "]);");
162 162 // pType.toString() - too verbose // pType.toString() - too verbose
 
... ... public class QueryTransformer implements ClassFileTransformer
167 167 // sb.append("System.err.println(\" para !prim " + i + ": \" + System.identityHashCode($args[" + i + "]));"); // sb.append("System.err.println(\" para !prim " + i + ": \" + System.identityHashCode($args[" + i + "]));");
168 168 //} //}
169 169 //sb.append("System.err.println(\" para " + i + ": class: \" + $args[" + i + "].getClass());"); //sb.append("System.err.println(\" para " + i + ": class: \" + $args[" + i + "].getClass());");
170 }
170 //}
171 171
172 172 /* /*
173 173 m.insertBefore("{" + sb.toString() + "}"); m.insertBefore("{" + sb.toString() + "}");
 
... ... public class QueryTransformer implements ClassFileTransformer
192 192 cc.detach(); cc.detach();
193 193 //System.err.println(" bytecode rewritten ok"); //System.err.println(" bytecode rewritten ok");
194 194 } catch (NotFoundException | CannotCompileException | IOException e) { } catch (NotFoundException | CannotCompileException | IOException e) {
195 ///System.err.println(" QueryTransformer.transform Exception: " + e);
195 System.err.println(" QueryTransformer.transform Exception: " + e);
196 196 } }
197 197
198 198 return byteCode; return byteCode;
File agent/ninedogs.TODO changed (mode: 100644) (index 5647d78..02995cd)
... ... Move from:
6 6 my_trace_put32(buf, &i, save_errno); my_trace_put32(buf, &i, save_errno);
7 7
8 8 to: to:
9 my_trace_put_err_int(buf, &i, va_arg(va, int), save_errno)
9 my_trace_put_err_int(buf, &i, va_arg(va, int), save_errno)
10
11 To add:
12 -
13
File agent/ninedogs.c changed (mode: 100644) (index b3a0dd7..be9c85d)
... ... struct mem_node
63 63 size_t size; size_t size;
64 64 struct mem_node *next; struct mem_node *next;
65 65 }; };
66 struct mem_node *mem_hash[64];
66 static __thread struct mem_node *mem_hash[64];
67 67
68 68 #define FD_NODE_DEV_NINEDOGS 1 #define FD_NODE_DEV_NINEDOGS 1
69 69 struct fd_node struct fd_node
 
... ... struct fd_node
72 72 unsigned int flags; unsigned int flags;
73 73 struct fd_node *next; struct fd_node *next;
74 74 }; };
75 static __thread struct fd_node *fd_nodes[32];
75 static __thread struct fd_node *fd_nodes[32]; // TODO must be shared, but we need locking
76 76
77 77 #define DLOPEN_MAX_ENTRIES 512 #define DLOPEN_MAX_ENTRIES 512
78 78 struct dlopen_node struct dlopen_node
 
... ... struct dlopen_node
82 82 unsigned int count; unsigned int count;
83 83 unsigned int pad; unsigned int pad;
84 84 }; };
85 static struct dlopen_node dlopen_nodes[DLOPEN_MAX_ENTRIES];
85 static struct dlopen_node dlopen_nodes[DLOPEN_MAX_ENTRIES]; // TODO: we need locking
86 86
87 87 // Custom allocator // Custom allocator
88 static unsigned char my_malloc[200ULL * 65536ULL];
88 static unsigned char my_malloc[20ULL * 65536ULL];
89 89 static unsigned long my_malloc_pos; static unsigned long my_malloc_pos;
90 90
91 91 static struct shared *shared; static struct shared *shared;
 
... ... static void my_trace_put_string_array(unsigned char *buf, unsigned int *i, char
290 290 } }
291 291 } }
292 292
293 static void my_trace_put_hostent(unsigned char *buf, unsigned int *i, struct hostent *he)
294 {
295 if (!he)
296 return;
297
298 int len = strlen(he->h_name);
299 my_trace_put8(buf, i, len);
300 my_trace_put(buf, i, he->h_name, len);
301
302 for (int j = 0; ; j++) {
303 if (!he->h_aliases[j]) {
304 my_trace_put8(buf, i, 0);
305 break;
306 }
307
308 len = strlen(he->h_aliases[j]);
309 my_trace_put8(buf, i, len);
310 my_trace_put(buf, i, he->h_aliases[j], len);
311 }
312
313 my_trace_put8(buf, i, he->h_addrtype);
314 my_trace_put8(buf, i, he->h_length);
315
316 int count = 0;
317 for (int j = 0; ; j++) {
318 if (!he->h_addr_list[j])
319 break;
320 count++;
321 }
322
323 my_trace_put8(buf, i, count);
324 for (int j = 0; j < count; j++) {
325 xlog(0, " DEBUG: addr[%d]=[%s]\n", j, he->h_addr_list[j]);
326 my_trace_put(buf, i, he->h_addr_list[j], he->h_length);
327 }
328 }
329
293 330 /* /*
294 * Returns how many byte were stored in
331 * Returns how many byte were stored in
295 332 */ */
296 333 static unsigned int my_trace_encode(unsigned char *buf, static unsigned int my_trace_encode(unsigned char *buf,
297 334 const char *func, const char type, int save_errno, va_list va) const char *func, const char type, int save_errno, va_list va)
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
408 445 case 'd': case 'd':
409 446 if (strcmp(func, "dlopen") == 0) { if (strcmp(func, "dlopen") == 0) {
410 447 char *filename = va_arg(va, char *); char *filename = va_arg(va, char *);
411 unsigned short len = strlen(filename);
448 unsigned short len = filename ? strlen(filename) : 0;
412 449 my_trace_put16(buf, &i, len); my_trace_put16(buf, &i, len);
413 450 my_trace_put(buf, &i, filename, len); my_trace_put(buf, &i, filename, len);
414 451 my_trace_put32(buf, &i, va_arg(va, int)); // flags my_trace_put32(buf, &i, va_arg(va, int)); // flags
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
465 502 if (ret == -1) if (ret == -1)
466 503 my_trace_put32(buf, &i, save_errno); my_trace_put32(buf, &i, save_errno);
467 504 } }
505 } else if ((strcmp(func, "fsync") == 0)
506 || (strcmp(func, "fdatasync") == 0)) {
507 my_trace_put32(buf, &i, va_arg(va, int)); // fd
508 if (type == 'r') {
509 int ret = va_arg(va, int);
510 my_trace_put32(buf, &i, ret);
511 if (ret == -1)
512 my_trace_put32(buf, &i, save_errno);
513 }
468 514 } break; } break;
469 515
470 516 case 'g': case 'g':
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
486 532 int ret = va_arg(va, int); int ret = va_arg(va, int);
487 533 my_trace_put32(buf, &i, ret); my_trace_put32(buf, &i, ret);
488 534 } }
489 } else if (strcmp(func, "gethostbyname") == 0) {
535 } else if (strcmp(func, "gethostbyname") == 0) { // send hostent?
490 536 char *name = va_arg(va, char *); char *name = va_arg(va, char *);
491 537 uint16_t len = strlen(name); uint16_t len = strlen(name);
492 538 my_trace_put16(buf, &i, len); my_trace_put16(buf, &i, len);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
497 543 if (ret == -1) if (ret == -1)
498 544 my_trace_put32(buf, &i, save_errno); my_trace_put32(buf, &i, save_errno);
499 545 } }
546 } else if (strcmp(func, "gethostbyname_r") == 0) {
547 char *name = va_arg(va, char *);
548 uint16_t len = strlen(name);
549 my_trace_put16(buf, &i, len);
550 my_trace_put(buf, &i, name, len);
551 if (type == 'r') {
552 int ret = va_arg(va, int);
553 int my_h_errno = va_arg(va, int);
554 struct hostent *he = va_arg(va, struct hostent *);
555 my_trace_put32(buf, &i, ret);
556 if (ret == -1)
557 my_trace_put32(buf, &i, my_h_errno);
558 else
559 my_trace_put_hostent(buf, &i, he);
560 }
500 561 } else if (strcmp(func, "getrandom") == 0) { } else if (strcmp(func, "getrandom") == 0) {
501 562 void *xbuf = NULL; void *xbuf = NULL;
502 563 if (type == 'r') if (type == 'r')
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
542 603 } break; } break;
543 604
544 605 case 'm': case 'm':
545 if (strcmp(func, "mysqli_close") == 0) {
606 if (strcmp(func, "mysqli_autocommit") == 0) {
607 struct db_autocommit *a = va_arg(va, struct db_autocommit *);
608 my_trace_put64(buf, &i, (uint64_t) a->link);
609 my_trace_put_bool(buf, &i, a->value);
610 if (type == 'r')
611 my_trace_put_bool(buf, &i, a->ret);
612 } else if (strcmp(func, "mysqli_close") == 0) {
546 613 struct conn *c = va_arg(va, struct conn *); struct conn *c = va_arg(va, struct conn *);
547 614 my_trace_put64(buf, &i, (uint64_t) c->dbh); my_trace_put64(buf, &i, (uint64_t) c->dbh);
548 615 if (type == 'r') if (type == 'r')
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
553 620 my_trace_put(buf, &i, c->conn_str, c->conn_str_len); my_trace_put(buf, &i, c->conn_str, c->conn_str_len);
554 621 if (type == 'r') if (type == 'r')
555 622 my_trace_put64(buf, &i, (uint64_t) c->dbh); my_trace_put64(buf, &i, (uint64_t) c->dbh);
556 } else if (strcmp(func, "mysqli_real_connect") == 0) {
557 struct conn *c = va_arg(va, struct conn *);
558 my_trace_put64(buf, &i, (uint64_t) c->dbh);
559 my_trace_put32(buf, &i, c->conn_str_len);
560 my_trace_put(buf, &i, c->conn_str, c->conn_str_len);
561 my_trace_put32(buf, &i, c->flags);
623 } else if (strcmp(func, "mysqli_fetch_all") == 0) {
624 struct query *q = va_arg(va, struct query *);
625 my_trace_put64(buf, &i, (uint64_t) q->res);
626 my_trace_put32(buf, &i, q->mode);
562 627 if (type == 'r') if (type == 'r')
563 my_trace_put_bool(buf, &i, c->ret);
564 /* TODO
565 } else if (strcmp(func, "mysqli_prepare") == 0) {
628 my_trace_put64(buf, &i, q->num);
629 } else if (strcmp(func, "mysqli_fetch_array") == 0) {
566 630 struct query *q = va_arg(va, struct query *); struct query *q = va_arg(va, struct query *);
567 my_trace_put64(buf, &i, (uint64_t) q->dbh);
568 my_trace_put16(buf, &i, q->q_len);
569 my_trace_put(buf, &i, q->q, q->q_len);
631 my_trace_put64(buf, &i, (uint64_t) q->res);
632 my_trace_put32(buf, &i, q->mode);
570 633 if (type == 'r') if (type == 'r')
571 my_trace_put_bool(buf, &i, c->ret);
572 */
634 my_trace_put8(buf, &i, q->ret);
635 } else if (strcmp(func, "mysqli_free_result") == 0) {
636 struct free_result *fr = va_arg(va, struct free_result *);
637 my_trace_put64(buf, &i, (uint64_t) fr->res);
638 } else if (strcmp(func, "mysqli_prepare") == 0) {
639 struct prepare *p = va_arg(va, struct prepare *);
640 my_trace_put64(buf, &i, (uint64_t) p->dbh);
641 my_trace_put16(buf, &i, p->q_len);
642 my_trace_put(buf, &i, p->q, p->q_len);
643 if (type == 'r')
644 my_trace_put64(buf, &i, (uint64_t) p->stmt);
573 645 } else if (strcmp(func, "mysqli_query") == 0) { } else if (strcmp(func, "mysqli_query") == 0) {
574 646 struct query *q = va_arg(va, struct query *); struct query *q = va_arg(va, struct query *);
575 647 my_trace_put64(buf, &i, (uint64_t) q->dbh); my_trace_put64(buf, &i, (uint64_t) q->dbh);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
577 649 my_trace_put(buf, &i, q->q, q->q_len); my_trace_put(buf, &i, q->q, q->q_len);
578 650 if (type == 'r') if (type == 'r')
579 651 my_trace_put64(buf, &i, (uint64_t) q->res); my_trace_put64(buf, &i, (uint64_t) q->res);
652 } else if (strcmp(func, "mysqli_real_connect") == 0) {
653 struct conn *c = va_arg(va, struct conn *);
654 my_trace_put64(buf, &i, (uint64_t) c->dbh);
655 my_trace_put32(buf, &i, c->conn_str_len);
656 my_trace_put(buf, &i, c->conn_str, c->conn_str_len);
657 my_trace_put32(buf, &i, c->flags);
658 if (type == 'r')
659 my_trace_put_bool(buf, &i, c->ret);
660 } else if (strcmp(func, "mysqli_stmt_execute") == 0) {
661 struct execute *e = va_arg(va, struct execute *);
662 my_trace_put64(buf, &i, (uint64_t) e->stmt);
663 if (type == 'c') {
664 my_trace_put16(buf, &i, e->params.len);
665 for (unsigned short j = 0; j < e->params.len; j++) {
666 struct params_array_one *pa = &e->params.list[j];
667 my_trace_put8(buf, &i, pa->type);
668 if (pa->type == ND_PARAMS_TYPE_LONG) {
669 my_trace_put64(buf, &i, pa->l);
670 } else if (pa->type == ND_PARAMS_TYPE_DOUBLE) {
671 my_trace_put_double(buf, &i, pa->d);
672 } else if (pa->type == ND_PARAMS_TYPE_STRING) {
673 my_trace_put16(buf, &i, pa->length);
674 my_trace_put(buf, &i, pa->str, pa->length);
675 }
676 }
677 }
678 if (type == 'r')
679 my_trace_put_bool(buf, &i, e->ret);
680 } else if (strcmp(func, "mysqli_stmt_prepare") == 0) {
681 struct prepare *p = va_arg(va, struct prepare *);
682 my_trace_put64(buf, &i, (uint64_t) p->stmt);
683 my_trace_put16(buf, &i, p->q_len);
684 my_trace_put(buf, &i, p->q, p->q_len);
685 if (type == 'r')
686 my_trace_put_bool(buf, &i, p->ret);
580 687 } break; } break;
581 688
582 689 case 'n': case 'n':
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
637 744 if (ret == -1) if (ret == -1)
638 745 my_trace_put32(buf, &i, save_errno); my_trace_put32(buf, &i, save_errno);
639 746 } }
747 } else if ((strcmp(func, "pread") == 0)
748 || (strcmp(func, "pread64") == 0)) {
749 void *buf2 = NULL;
750 my_trace_put32(buf, &i, va_arg(va, int)); // fd
751 if (type == 'r')
752 buf2 = va_arg(va, void *);
753 my_trace_put64(buf, &i, va_arg(va, size_t)); // count
754 my_trace_put64(buf, &i, va_arg(va, off_t)); // offset
755 if (type == 'r') {
756 ssize_t ret = va_arg(va, ssize_t);
757 my_trace_put64(buf, &i, ret);
758 if (ret > 0) {
759 unsigned short max = ret;
760 if (max > 128)
761 max = 128;
762 my_trace_put16(buf, &i, max);
763 my_trace_put(buf, &i, buf2, max); // data
764 } else if (ret == -1)
765 my_trace_put32(buf, &i, save_errno);
766 }
767 } else if (strcmp(func, "pthread_setname_np") == 0) {
768 my_trace_put64(buf, &i, (uint64_t) va_arg(va, pthread_t));
769 char *name = va_arg(va, char *);
770 unsigned short len = strlen(name);
771 my_trace_put16(buf, &i, len);
772 my_trace_put(buf, &i, name, len);
773 int ret = va_arg(va, int);
774 my_trace_put32(buf, &i, ret);
775 if (ret == -1)
776 my_trace_put32(buf, &i, save_errno);
777 } else if (strcmp(func, "pthread_attr_setstacksize") == 0) {
778 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // attr
779 my_trace_put64(buf, &i, (uint64_t) va_arg(va, size_t)); // stack size
780 int ret = va_arg(va, int);
781 my_trace_put32(buf, &i, ret);
782 if (ret == -1)
783 my_trace_put32(buf, &i, save_errno);
784 } else if (strcmp(func, "pthread_create") == 0) {
785 my_trace_put32(buf, &i, (uint64_t) va_arg(va, uint32_t)); // thread
786 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // attr TODO - how to encode it?
787 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // arg
788 int ret = va_arg(va, int);
789 my_trace_put32(buf, &i, ret);
790 if (ret == -1)
791 my_trace_put32(buf, &i, save_errno);
792 } else if ((strcmp(func, "pwrite") == 0)
793 || (strcmp(func, "pwrite64") == 0)) {
794 void *buf2 = NULL;
795 my_trace_put32(buf, &i, va_arg(va, int)); // fd
796 if (type == 'c')
797 buf2 = va_arg(va, void *);
798 size_t count = va_arg(va, size_t);
799 my_trace_put64(buf, &i, count);
800 my_trace_put64(buf, &i, va_arg(va, off_t)); // offset
801 if (type == 'c') {
802 unsigned short max = count;
803 if (max > 128) max = 128;
804 my_trace_put16(buf, &i, max);
805 my_trace_put(buf, &i, buf2, max); // data
806 } else {
807 ssize_t ret = va_arg(va, ssize_t);
808 my_trace_put64(buf, &i, ret);
809 if (ret == -1)
810 my_trace_put32(buf, &i, save_errno);
811 }
640 812 } else if (strcmp(func, "pg_close") == 0) { } else if (strcmp(func, "pg_close") == 0) {
641 uint64_t h = va_arg(va, uint64_t); // handle
642 my_trace_put64(buf, &i, h);
813 struct conn *c = va_arg(va, struct conn *);
814 my_trace_put64(buf, &i, (uint64_t) c->dbh);
643 815 } else if ((strcmp(func, "pg_connect") == 0) } else if ((strcmp(func, "pg_connect") == 0)
644 816 || (strcmp(func, "pg_pconnect") == 0)) { || (strcmp(func, "pg_pconnect") == 0)) {
645 char *cs = va_arg(va, char *);
646 unsigned int cs_len = va_arg(va, unsigned int);
647 my_trace_put32(buf, &i, cs_len);
648 my_trace_put(buf, &i, cs, cs_len);
817 struct conn *c = va_arg(va, struct conn *);
818 my_trace_put32(buf, &i, c->conn_str_len);
819 my_trace_put(buf, &i, c->conn_str, c->conn_str_len);
649 820 if (type == 'r') if (type == 'r')
650 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
821 my_trace_put64(buf, &i, (uint64_t) c->dbh);
651 822 } else if (strcmp(func, "pg_free_result") == 0) { } else if (strcmp(func, "pg_free_result") == 0) {
652 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // res
653 my_trace_put8(buf, &i, va_arg(va, int)); // ret
823 struct free_result *fr = va_arg(va, struct free_result *);
824 my_trace_put64(buf, &i, (uint64_t) fr->res);
825 my_trace_put8(buf, &i, fr->ok);
654 826 } else if ((strcmp(func, "pg_query") == 0) } else if ((strcmp(func, "pg_query") == 0)
655 827 || (strcmp(func, "pg_query_params") == 0) || (strcmp(func, "pg_query_params") == 0)
656 828 || (strcmp(func, "pg_send_query") == 0) || (strcmp(func, "pg_send_query") == 0)
657 829 || (strcmp(func, "pg_send_query_params") == 0)) { || (strcmp(func, "pg_send_query_params") == 0)) {
658 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // dbh
659 char *q = va_arg(va, void *);
660 unsigned short q_len = va_arg(va, unsigned int);
661 my_trace_put16(buf, &i, q_len);
662 my_trace_put(buf, &i, q, q_len);
830 struct query *q = va_arg(va, struct query *);
831 my_trace_put64(buf, &i, (uint64_t) q->dbh);
832 my_trace_put16(buf, &i, q->q_len);
833 my_trace_put(buf, &i, q->q, q->q_len);
663 834 if (type == 'c') { if (type == 'c') {
664 uint16_t params_len = va_arg(va, unsigned);
665 my_trace_put16(buf, &i, params_len);
666 uint16_t max = params_len;
667 if (max > ND_PARAMS_MAX) max = ND_PARAMS_MAX;
668 my_trace_put16(buf, &i, max);
669 struct params_array *pa = va_arg(va, void *);
670 for (unsigned short j = 0; j < max; j++) {
835 my_trace_put16(buf, &i, q->params.len);
836 for (unsigned short j = 0; j < q->params.len; j++) {
837 struct params_array_one *pa = &q->params.list[j];
671 838 my_trace_put8(buf, &i, pa->type); my_trace_put8(buf, &i, pa->type);
672 839 if (pa->type == ND_PARAMS_TYPE_LONG) { if (pa->type == ND_PARAMS_TYPE_LONG) {
673 840 my_trace_put64(buf, &i, pa->l); my_trace_put64(buf, &i, pa->l);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
677 844 my_trace_put16(buf, &i, pa->length); my_trace_put16(buf, &i, pa->length);
678 845 my_trace_put(buf, &i, pa->str, pa->length); my_trace_put(buf, &i, pa->str, pa->length);
679 846 } }
680 pa++;
681 847 } }
682 848 } }
683 849 if (type == 'r') { if (type == 'r') {
684 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // res
685 my_trace_put64(buf, &i, (uint64_t) va_arg(va, uint64_t)); // rows
686 my_trace_put64(buf, &i, (uint64_t) va_arg(va, uint64_t)); // aff
850 my_trace_put64(buf, &i, (uint64_t) q->res);
851 my_trace_put64(buf, &i, q->num);
852 my_trace_put64(buf, &i, q->aff);
687 853 } }
688 854 } else if (strcmp(func, "pg_get_result") == 0) { } else if (strcmp(func, "pg_get_result") == 0) {
689 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // dbh
690 (void) va_arg(va, void *); // ignore q
691 (void) va_arg(va, unsigned int); // ignore q_len
855 struct query *q = va_arg(va, struct query *);
856 my_trace_put64(buf, &i, (uint64_t) q->dbh);
692 857 if (type == 'r') { if (type == 'r') {
693 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // res
694 my_trace_put64(buf, &i, (uint64_t) va_arg(va, uint64_t)); // rows
695 my_trace_put64(buf, &i, (uint64_t) va_arg(va, uint64_t)); // aff
858 my_trace_put64(buf, &i, (uint64_t) q->res);
859 my_trace_put64(buf, &i, (uint64_t) q->num);
860 my_trace_put64(buf, &i, (uint64_t) q->aff);
696 861 } }
697 862 } break; } break;
698 863
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
811 976 my_trace_put32(buf, &i, ret); my_trace_put32(buf, &i, ret);
812 977 if (ret == -1) if (ret == -1)
813 978 my_trace_put32(buf, &i, save_errno); my_trace_put32(buf, &i, save_errno);
979 } else if (strcmp(func, "sqlite3_bind_double") == 0) {
980 my_trace_put64(buf, &i, va_arg(va, uint64_t)); // stmt
981 my_trace_put32(buf, &i, va_arg(va, int)); // index
982 my_trace_put64(buf, &i, va_arg(va, double)); // value
983 my_trace_put32(buf, &i, va_arg(va, int)); // ret
984 } else if (strcmp(func, "sqlite3_bind_int") == 0) {
985 my_trace_put64(buf, &i, va_arg(va, uint64_t)); // stmt
986 my_trace_put32(buf, &i, va_arg(va, int)); // index
987 my_trace_put32(buf, &i, va_arg(va, int)); // value
988 my_trace_put32(buf, &i, va_arg(va, int)); // ret
989 } else if (strcmp(func, "sqlite3_bind_int64") == 0) {
990 my_trace_put64(buf, &i, va_arg(va, uint64_t)); // stmt
991 my_trace_put32(buf, &i, va_arg(va, int)); // index
992 my_trace_put64(buf, &i, va_arg(va, int64_t)); // value
993 my_trace_put32(buf, &i, va_arg(va, int)); // ret
994 } else if (strcmp(func, "sqlite3_bind_text") == 0) {
995 my_trace_put64(buf, &i, va_arg(va, uint64_t)); // stmt
996 my_trace_put32(buf, &i, va_arg(va, int)); // index
997 char *value = va_arg(va, char *);
998 int max = va_arg(va, int);
999 if (!value)
1000 max = 0;
1001 else if (max < 0)
1002 max = strlen(value);
1003 my_trace_put16(buf, &i, max);
1004 my_trace_put(buf, &i, value, max); // value
1005 my_trace_put32(buf, &i, va_arg(va, int)); // ret
1006 } else if (strcmp(func, "sqlite3_finalize") == 0) {
1007 my_trace_put64(buf, &i, va_arg(va, uint64_t)); // stmt
1008 my_trace_put32(buf, &i, va_arg(va, int)); // ret
814 1009 } else if (strcmp(func, "sqlite3_open_v2") == 0) { } else if (strcmp(func, "sqlite3_open_v2") == 0) {
815 1010 char *filename = va_arg(va, char *); char *filename = va_arg(va, char *);
816 1011 uint16_t filename_len = strlen(filename); uint16_t filename_len = strlen(filename);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
850 1045 my_trace_put32(buf, &i, va_arg(va, int)); // ret my_trace_put32(buf, &i, va_arg(va, int)); // ret
851 1046 } else if (strcmp(func, "stat") == 0) { } else if (strcmp(func, "stat") == 0) {
852 1047 char *pathname = va_arg(va, char *); char *pathname = va_arg(va, char *);
853 unsigned short len = strlen(pathname);
1048 unsigned short len = pathname ? strlen(pathname) : 0;
854 1049 my_trace_put16(buf, &i, len); my_trace_put16(buf, &i, len);
855 1050 my_trace_put(buf, &i, pathname, len); my_trace_put(buf, &i, pathname, len);
856 struct stat *s = va_arg(va, void *);
857 my_trace_put_stat(buf, &i, s);
858 1051 if (type == 'r') { if (type == 'r') {
1052 struct stat *s = va_arg(va, void *);
1053 my_trace_put_stat(buf, &i, s);
859 1054 int ret = va_arg(va, int); int ret = va_arg(va, int);
860 1055 my_trace_put32(buf, &i, ret); my_trace_put32(buf, &i, ret);
861 1056 if (ret == -1) if (ret == -1)
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
917 1112
918 1113 void my_trace(const char *func, const char type, ...) void my_trace(const char *func, const char type, ...)
919 1114 { {
1115 static __thread unsigned char out[64000]; // I had to reduce this for .NET! Stack too small!
920 1116 int save_errno; int save_errno;
921 1117 va_list va; va_list va;
922 1118 int locked, r; int locked, r;
 
... ... void my_trace(const char *func, const char type, ...)
935 1131 locked = 0; locked = 0;
936 1132 do { do {
937 1133 unsigned int ava, i; unsigned int ava, i;
938 unsigned char out[1000000];
939 1134
940 1135 va_start(va, type); va_start(va, type);
941 1136 i = my_trace_encode(out, func, type, save_errno, va); i = my_trace_encode(out, func, type, save_errno, va);
 
... ... ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
1920 2115 rest -= msg->msg_iov[i].iov_len; rest -= msg->msg_iov[i].iov_len;
1921 2116 } }
1922 2117 } }
1923
1924 2118 my_trace(__func__, 'r', sockfd, msg, flags, ret); my_trace(__func__, 'r', sockfd, msg, flags, ret);
1925 2119
1926 2120 return ret; return ret;
 
... ... struct hostent *gethostbyname(const char *name)
2050 2244 return ret; return ret;
2051 2245 } }
2052 2246
2247 static int (*old_gethostbyname_r)(const char *name, struct hostent *restrict ret,
2248 char *restrict buf, size_t buflen,
2249 struct hostent **restrict result,
2250 int *restrict h_errnop);
2251 int gethostbyname_r(const char *name, struct hostent *restrict ret,
2252 char *restrict buf, size_t buflen,
2253 struct hostent **restrict result,
2254 int *restrict h_errnop)
2255 {
2256 int r;
2257
2258 if (!old_gethostbyname_r)
2259 old_gethostbyname_r = ninedogs_dlsym("gethostbyname_r");
2260
2261 xlog(100, "gethostbyname_r('%s', buflen=%zu)\n", name, buflen);
2262 my_trace(__func__, 'c', name);
2263 r = old_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
2264 xlog(100, "gethostbyname_r('%s', buflen=%zu) = %d h_errno=%d *result=%p\n",
2265 name, buflen, r, *h_errnop, result ? *result : NULL);
2266 my_trace(__func__, 'r', name, r, *h_errnop, *result);
2267
2268 return r;
2269 }
2270
2053 2271 int getaddrinfo(const char *restrict node, const char *restrict service, int getaddrinfo(const char *restrict node, const char *restrict service,
2054 2272 const struct addrinfo *restrict hints, struct addrinfo **restrict res) const struct addrinfo *restrict hints, struct addrinfo **restrict res)
2055 2273 { {
 
... ... int getaddrinfo(const char *restrict node, const char *restrict service,
2065 2283 return ret; return ret;
2066 2284 } }
2067 2285
2068 // TODO: not yet in trace
2069 2286 int pthread_create(pthread_t *restrict thread, int pthread_create(pthread_t *restrict thread,
2070 2287 const pthread_attr_t *restrict attr, void *(*start_routine)(void *), const pthread_attr_t *restrict attr, void *(*start_routine)(void *),
2071 2288 void *restrict arg) void *restrict arg)
2072 2289 { {
2073 2290 int ret; int ret;
2074 2291
2075 //xlog(2, "pthread_create\n");
2076
2292 //xlog(2, "%s\n", __func__);
2077 2293 ret = old_pthread_create(thread, attr, start_routine, arg); ret = old_pthread_create(thread, attr, start_routine, arg);
2078 my_trace(__func__, 'R', thread, attr, arg, ret);
2294 my_trace(__func__, 'R', ret == 0 ? *thread : 0, attr, arg, ret);
2079 2295
2080 2296 return ret; return ret;
2081 2297 } }
2082 2298
2299 // TODO: trace
2083 2300 int pthread_join(pthread_t thread, void **retval) int pthread_join(pthread_t thread, void **retval)
2084 2301 { {
2085 2302 int ret; int ret;
2086 2303
2087 2304 //xlog(2, "pthread_join\n"); //xlog(2, "pthread_join\n");
2088
2089 2305 ret = old_pthread_join(thread, retval); ret = old_pthread_join(thread, retval);
2090 my_trace(__func__, 'R', retval, ret);
2306 my_trace(__func__, 'R', ret == 0 ? *retval : NULL, ret);
2091 2307
2092 2308 return ret; return ret;
2093 2309 } }
2094 2310
2095 2311 #if 0 #if 0
2096 // this crashes!
2097 2312 int pthread_attr_init(pthread_attr_t *attr) int pthread_attr_init(pthread_attr_t *attr)
2098 2313 { {
2099 2314 int ret; int ret;
2100 2315
2101 xlog(2, "%s\n", __func__);
2316 if (!old_pthread_attr_init)
2317 old_pthread_attr_init = ninedogs_dlsym("pthread_attr_init");
2102 2318
2319 xlog(2, "%s\n", __func__);
2103 2320 ret = old_pthread_attr_init(attr); ret = old_pthread_attr_init(attr);
2104 2321 my_trace(__func__, 'R', attr, ret); my_trace(__func__, 'R', attr, ret);
2105 2322
 
... ... int pthread_attr_init(pthread_attr_t *attr)
2110 2327 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
2111 2328 { {
2112 2329 int ret; int ret;
2113 //xlog(2, "pthread_attr_setstacksize(%zu)\n", stacksize);
2330
2331 if (!old_pthread_attr_setstacksize)
2332 old_pthread_attr_setstacksize = ninedogs_dlsym("pthread_attr_setstacksize");
2333
2334 xlog(2, "pthread_attr_setstacksize(%p, %zu)\n", attr, stacksize);
2114 2335
2115 2336 ret = old_pthread_attr_setstacksize(attr, stacksize); ret = old_pthread_attr_setstacksize(attr, stacksize);
2116 2337 my_trace(__func__, 'R', attr, stacksize, ret); my_trace(__func__, 'R', attr, stacksize, ret);
 
... ... int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
2118 2339 return ret; return ret;
2119 2340 } }
2120 2341
2342 static int (*old_pthread_setname_np)(pthread_t thread, const char *name);
2343 int pthread_setname_np(pthread_t thread, const char *name)
2344 {
2345 int ret;
2346
2347 if (!old_pthread_setname_np)
2348 old_pthread_setname_np = ninedogs_dlsym("pthread_setname_np");
2349
2350 xlog(2, "pthread_setname_np(%lu, %s)\n", thread, name);
2351 ret = old_pthread_setname_np(thread, name);
2352 my_trace(__func__, 'R', thread, name, ret);
2353
2354 return ret;
2355 }
2356
2121 2357 // TODO: not yet in tracing (done on nd-trace) // TODO: not yet in tracing (done on nd-trace)
2122 2358 int getsockopt(int sockfd, int level, int optname, void *restrict optval, int getsockopt(int sockfd, int level, int optname, void *restrict optval,
2123 2359 socklen_t *restrict optlen) socklen_t *restrict optlen)
 
... ... void *dlopen(const char *filename, int flags)
2317 2553 my_trace(__func__, 'c', filename, flags); my_trace(__func__, 'c', filename, flags);
2318 2554 ret = old_dlopen(filename, flags); ret = old_dlopen(filename, flags);
2319 2555 my_trace(__func__, 'r', filename, flags, ret); my_trace(__func__, 'r', filename, flags, ret);
2320 xlog(100, "%s(%s, 0x%x) = %p\n", __func__, filename, flags, ret);
2321 if (ret) {
2556 if (filename && ret) {
2322 2557 // TODO: should I add only 'flags=GLOBAL' entries? // TODO: should I add only 'flags=GLOBAL' entries?
2323 2558 unsigned found = 0, first_free = DLOPEN_MAX_ENTRIES; unsigned found = 0, first_free = DLOPEN_MAX_ENTRIES;
2324 2559 for (unsigned i = 0; i < DLOPEN_MAX_ENTRIES; i++) { for (unsigned i = 0; i < DLOPEN_MAX_ENTRIES; i++) {
 
... ... int listen(int sock, int backlog)
2477 2712 void syslog(int priority, const char *format, ...) void syslog(int priority, const char *format, ...)
2478 2713 { {
2479 2714 va_list va; va_list va;
2480 char buf[64000];
2715 char buf[4096];
2481 2716
2482 2717 if (!old_syslog) if (!old_syslog)
2483 2718 ninedogs_init(); ninedogs_init();
 
... ... int stat(const char *restrict pathname, struct stat *restrict statbuf)
2534 2769 if (!old_stat) if (!old_stat)
2535 2770 ninedogs_init(); ninedogs_init();
2536 2771
2537 xlog(100, "%s(%s, %p)\n",
2538 __func__, pathname, statbuf);
2772 xlog(100, "%s(%s, %p)\n", __func__, pathname, statbuf);
2539 2773
2540 2774 my_trace(__func__, 'c', pathname); my_trace(__func__, 'c', pathname);
2541 2775 ret = old_stat(pathname, statbuf); ret = old_stat(pathname, statbuf);
 
... ... int fork(void)
2559 2793 return ret; return ret;
2560 2794 } }
2561 2795
2796 static int (*old_fsync)(int fd);
2797 int fsync(int fd)
2798 {
2799 int ret;
2800
2801 if (!old_fsync)
2802 old_fsync = ninedogs_dlsym("fsync");
2803
2804 xlog(100, "%s(%d)\n", __func__, fd);
2805 my_trace(__func__, 'c', fd);
2806 ret = old_fsync(fd);
2807 my_trace(__func__, 'r', fd, ret);
2808
2809 return ret;
2810 }
2811
2812 static int (*old_fdatasync)(int fd);
2813 int fdatasync(int fd)
2814 {
2815 int ret;
2816
2817 if (!old_fdatasync)
2818 old_fdatasync = ninedogs_dlsym("fdatasync");
2819
2820 xlog(100, "%s(%d)\n", __func__, fd);
2821 my_trace(__func__, 'c', fd);
2822 ret = old_fdatasync(fd);
2823 my_trace(__func__, 'r', fd, ret);
2824
2825 return ret;
2826 }
2827
2828 static ssize_t (*old_pread)(int fd, void *buf, size_t count, off_t offset);
2829 ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2830 {
2831 ssize_t ret;
2832
2833 if (!old_pread)
2834 old_pread = ninedogs_dlsym("pread");
2835
2836 xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset);
2837 my_trace(__func__, 'c', fd, count, offset);
2838 ret = old_pread(fd, buf, count, offset);
2839 my_trace(__func__, 'r', fd, buf, count, offset, ret);
2840
2841 return ret;
2842 }
2843
2844 static ssize_t (*old_pread64)(int fd, void *buf, size_t count, off_t offset);
2845 ssize_t pread64(int fd, void *buf, size_t count, off_t offset)
2846 {
2847 ssize_t ret;
2848
2849 if (!old_pread64)
2850 old_pread64 = ninedogs_dlsym("pread64");
2851
2852 xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset);
2853 my_trace(__func__, 'c', fd, count, offset);
2854 ret = old_pread64(fd, buf, count, offset);
2855 my_trace(__func__, 'r', fd, buf, count, offset, ret);
2856
2857 return ret;
2858 }
2859
2860 static ssize_t (*old_pwrite)(int fd, const void *buf, size_t count, off_t offset);
2861 ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2862 {
2863 ssize_t ret;
2864
2865 if (!old_pwrite)
2866 old_pwrite = ninedogs_dlsym("pwrite");
2867
2868 xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset);
2869 my_trace(__func__, 'c', fd, buf, count, offset);
2870 ret = old_pwrite(fd, buf, count, offset);
2871 my_trace(__func__, 'r', fd, count, offset, ret);
2872
2873 return ret;
2874 }
2875
2876 static ssize_t (*old_pwrite64)(int fd, const void *buf, size_t count, off_t offset);
2877 ssize_t pwrite64(int fd, const void *buf, size_t count, off_t offset)
2878 {
2879 ssize_t ret;
2880
2881 if (!old_pwrite64)
2882 old_pwrite64 = ninedogs_dlsym("pwrite64");
2883
2884 xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset);
2885 my_trace(__func__, 'c', fd, buf, count, offset);
2886 ret = old_pwrite64(fd, buf, count, offset);
2887 my_trace(__func__, 'r', fd, count, offset, ret);
2888
2889 return ret;
2890 }
2891
2562 2892 static int (*old_sqlite3_open)(const char *, void **); static int (*old_sqlite3_open)(const char *, void **);
2563 2893 int sqlite3_open(const char *filename, void **ppdb) int sqlite3_open(const char *filename, void **ppdb)
2564 2894 { {
 
... ... int sqlite3_prepare_v2(void *h, const char *sql, int nByte, void **stmt, const c
2650 2980 return ret; return ret;
2651 2981 } }
2652 2982
2983 static int (*old_sqlite3_finalize)(void *);
2984 int sqlite3_finalize(void *pstmt)
2985 {
2986 int ret;
2987
2988 if (!old_sqlite3_finalize)
2989 old_sqlite3_finalize = ninedogs_dlsym("sqlite3_finalize");
2990
2991 ret = old_sqlite3_finalize(pstmt);
2992 xlog(100, "%s(pstmt=%p) = %d\n", __func__, pstmt);
2993 my_trace(__func__, 'R', pstmt, ret);
2994
2995 return ret;
2996 }
2997
2653 2998 static int (*old_sqlite3_step)(void *); static int (*old_sqlite3_step)(void *);
2654 2999 int sqlite3_step(void *stmt) int sqlite3_step(void *stmt)
2655 3000 { {
 
... ... int sqlite3_step(void *stmt)
2666 3011 return ret; return ret;
2667 3012 } }
2668 3013
3014 static int (*old_sqlite3_bind_double)(void *, int, double);
3015 int sqlite3_bind_double(void *stmt, int index, double value)
3016 {
3017 int ret;
3018
3019 if (!old_sqlite3_bind_double)
3020 old_sqlite3_bind_double = ninedogs_dlsym("sqlite3_bind_double");
3021
3022 ret = old_sqlite3_bind_double(stmt, index, value);
3023 xlog(100, "%s(stmt=%p, %d, %f) = %d\n", __func__, stmt, index, value, ret);
3024 my_trace(__func__, 'R', stmt, index, value, ret);
3025
3026 return ret;
3027 }
3028
3029 static int (*old_sqlite3_bind_int)(void *, int, int);
3030 int sqlite3_bind_int(void *stmt, int index, int value)
3031 {
3032 int ret;
3033
3034 if (!old_sqlite3_bind_int)
3035 old_sqlite3_bind_int = ninedogs_dlsym("sqlite3_bind_int");
3036
3037 ret = old_sqlite3_bind_int(stmt, index, value);
3038 xlog(100, "%s(stmt=%p, %d, %d) = %d\n", __func__, stmt, index, value, ret);
3039 my_trace(__func__, 'R', stmt, index, value, ret);
3040
3041 return ret;
3042 }
3043
3044 static int (*old_sqlite3_bind_int64)(void *, int, uint64_t);
3045 int sqlite3_bind_int64(void *stmt, int index, uint64_t value)
3046 {
3047 int ret;
3048
3049 if (!old_sqlite3_bind_int64)
3050 old_sqlite3_bind_int64 = ninedogs_dlsym("sqlite3_bind_int64");
3051
3052 ret = old_sqlite3_bind_int64(stmt, index, value);
3053 xlog(100, "%s(stmt=%p, %d, %ld) = %d\n", __func__, stmt, index, value, ret);
3054 my_trace(__func__, 'R', stmt, index, value, ret);
3055
3056 return ret;
3057 }
3058
3059 static int (*old_sqlite3_bind_text)(void *, int, const char *, int, void *);
3060 int sqlite3_bind_text(void *stmt, int index, const char *value, int len, void *func)
3061 {
3062 int ret;
3063
3064 if (!old_sqlite3_bind_text)
3065 old_sqlite3_bind_text = ninedogs_dlsym("sqlite3_bind_text");
3066
3067 ret = old_sqlite3_bind_text(stmt, index, value, len, func);
3068 xlog(100, "%s(stmt=%p, %d, '%s', len=%d) = %d\n", __func__, stmt, index, value, len, ret);
3069 my_trace(__func__, 'R', stmt, index, value, len, ret);
3070
3071 return ret;
3072 }
3073
File agent/php.c changed (mode: 100644) (index 94e2548..547b340)
... ... static void php_zed_dump(const char *prefix, struct zend_execute_data *p)
319 319 } }
320 320 } }
321 321
322 static void zend_array_to_params_array(struct query *q, struct zend_array *za)
322 static void zend_array_to_params_array(struct params_array *p, struct zend_array *za)
323 323 { {
324 unsigned int i = 0, max;
324 unsigned int i = 0;
325 325
326 326 xlog(100, " nTableMask=0x%x nNumUsed=%u nNumOfElements=%u nTableSize=%u" xlog(100, " nTableMask=0x%x nNumUsed=%u nNumOfElements=%u nTableSize=%u"
327 327 " nInternalPointer=%u flags=0x%x[%s]\n", " nInternalPointer=%u flags=0x%x[%s]\n",
328 328 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize,
329 329 za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : ""); za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : "");
330 330
331 max = za->nNumUsed;
332 if (max > ND_PARAMS_MAX)
333 max = ND_PARAMS_MAX;
331 p->len = za->nNumUsed;
332 if (p->len > ND_PARAMS_MAX)
333 p->len = ND_PARAMS_MAX;
334 334
335 335 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed; struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
336 336 for (; bs != be; bs++) { for (; bs != be; bs++) {
 
... ... static void zend_array_to_params_array(struct query *q, struct zend_array *za)
354 354 bs, bs->h, zs, php_get_type(_z), php_get_value(_z)); bs, bs->h, zs, php_get_type(_z), php_get_value(_z));
355 355
356 356 if (_z->u1.v.type == 4) { if (_z->u1.v.type == 4) {
357 q->params[i].type = ND_PARAMS_TYPE_LONG;
358 q->params[i].l = _z->value.lval;
357 p->list[i].type = ND_PARAMS_TYPE_LONG;
358 p->list[i].l = _z->value.lval;
359 359 } else if (_z->u1.v.type == 5) { } else if (_z->u1.v.type == 5) {
360 q->params[i].type = ND_PARAMS_TYPE_DOUBLE;
361 q->params[i].d = _z->value.dval;
360 p->list[i].type = ND_PARAMS_TYPE_DOUBLE;
361 p->list[i].d = _z->value.dval;
362 362 } else if (_z->u1.v.type == 6) { } else if (_z->u1.v.type == 6) {
363 q->params[i].type = ND_PARAMS_TYPE_STRING;
363 p->list[i].type = ND_PARAMS_TYPE_STRING;
364 364 struct zend_string *zs = _z->value.str; struct zend_string *zs = _z->value.str;
365 q->params[i].str = zs->val;
366 q->params[i].length = zs->len;
365 p->list[i].str = zs->val;
366 p->list[i].length = zs->len;
367 367 } }
368 368
369 369 i++; i++;
370 if (i == max)
370 if (i == p->len)
371 371 break; break;
372 372 } }
373
374 q->params_len = za->nNumUsed;
375 373 } }
376 374
377 375 void *(*old_pg_last_error)(struct zend_execute_data *, struct zval *); void *(*old_pg_last_error)(struct zend_execute_data *, struct zval *);
 
... ... static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv)
510 508 { {
511 509 void *ret; void *ret;
512 510 unsigned int s; unsigned int s;
511 struct zval *z;
513 512 struct free_result fr; struct free_result fr;
514 513
515 514 unsigned int num_args = e->This.u2.num_args; unsigned int num_args = e->This.u2.num_args;
 
... ... static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv)
518 517 //php_zval_dump(" retv: ", retv); //php_zval_dump(" retv: ", retv);
519 518
520 519 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
521 struct zval *z = (struct zval *) e + s;
522
523 520 fr.type = 'P'; fr.type = 'P';
521
522 // res
523 z = (struct zval *) e + s; s++;
524 524 fr.res = z->value.p; fr.res = z->value.p;
525 525
526 ret = old_pg_free_result(e, retv); // ret will be NULL!
526 ret = old_pg_free_result(e, retv);
527 527 // 'ret' is null here // 'ret' is null here
528 528
529 529 if (retv->u1.v.type == 3) { // true if (retv->u1.v.type == 3) { // true
 
... ... static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
632 632 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
633 633 para = (struct zval *) e + s; para = (struct zval *) e + s;
634 634 qs.type = 'P'; // if dbh is null, we do not know the type qs.type = 'P'; // if dbh is null, we do not know the type
635 qs.params_len = 0;
635 qs.params.len = 0;
636 636
637 637 if (num_args == 2) { if (num_args == 2) {
638 638 // link // link
 
... ... static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv)
692 692
693 693 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
694 694 qs.type = 'P'; qs.type = 'P';
695 qs.params_len = 0;
695 qs.params.len = 0;
696 696
697 697 // link // link
698 698 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
 
... ... static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv)
744 744 para = (struct zval *) e + s; para = (struct zval *) e + s;
745 745 qs.type = 'P'; qs.type = 'P';
746 746 qs.q = NULL; qs.q = NULL;
747 qs.params_len = 0;
747 qs.params.len = 0;
748 748
749 749 // link // link
750 750 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
 
... ... static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv)
818 818 // params (array) // params (array)
819 819 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
820 820 struct zend_array *za = z->value.arr; struct zend_array *za = z->value.arr;
821 zend_array_to_params_array(&qs, za);
821 zend_array_to_params_array(&qs.params, za);
822 822
823 823 ninedogs_process_db("pg_query_params", NINEDOGS_DB_QUERY_START, &qs); ninedogs_process_db("pg_query_params", NINEDOGS_DB_QUERY_START, &qs);
824 824 ret = old_pg_query_params(e, retv); ret = old_pg_query_params(e, retv);
 
... ... static void *my_pg_send_query_params(struct zend_execute_data *e, struct zval *r
880 880 // params (array) // params (array)
881 881 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
882 882 struct zend_array *za = z->value.arr; struct zend_array *za = z->value.arr;
883 zend_array_to_params_array(&qs, za);
883 zend_array_to_params_array(&qs.params, za);
884 884
885 885 ninedogs_process_db("pg_send_query_params", NINEDOGS_DB_QUERY_START, &qs); ninedogs_process_db("pg_send_query_params", NINEDOGS_DB_QUERY_START, &qs);
886 886 ret = old_pg_send_query_params(e, retv); ret = old_pg_send_query_params(e, retv);
 
... ... static void *my_mysqli_connect(struct zend_execute_data *e, struct zval *retv)
921 921
922 922 if (num_args >= 1) { // host if (num_args >= 1) { // host
923 923 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
924 php_zval_dump(" host: ", z);
924 //php_zval_dump(" host: ", z);
925 925 if (z->u1.v.type == 6) // string if (z->u1.v.type == 6) // string
926 926 host = z->value.str->val; host = z->value.str->val;
927 927 } }
 
... ... static void *my_mysqli_real_connect(struct zend_execute_data *e, struct zval *re
1004 1004
1005 1005 if (num_args >= 2) { // host if (num_args >= 2) { // host
1006 1006 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
1007 php_zval_dump(" host: ", z);
1007 //php_zval_dump(" host: ", z);
1008 1008 if (z->u1.v.type == 6) // string if (z->u1.v.type == 6) // string
1009 1009 host = z->value.str->val; host = z->value.str->val;
1010 1010 } }
 
... ... static void *my_mysqli_query(struct zend_execute_data *e, struct zval *retv)
1085 1085 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1086 1086 para = (struct zval *) e + s; para = (struct zval *) e + s;
1087 1087 qs.type = 'M'; qs.type = 'M';
1088 qs.params_len = 0;
1088 qs.params.len = 0;
1089 1089
1090 1090 // link // link
1091 1091 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
 
... ... static void *my_mysqli_close(struct zend_execute_data *e, struct zval *retv)
1146 1146 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1147 1147
1148 1148 unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1149 struct zval *para = (struct zval *) e + s;
1150 1149 c.type = 'M'; c.type = 'M';
1151 1150
1152 1151 // link // link
 
... ... static void *my_mysqli_close(struct zend_execute_data *e, struct zval *retv)
1172 1171 return ret; return ret;
1173 1172 } }
1174 1173
1174 void *(*old_mysqli_fetch_all)(struct zend_execute_data *, struct zval *);
1175 static void *my_mysqli_fetch_all(struct zend_execute_data *e, struct zval *retv)
1176 {
1177 struct query q;
1178
1179 unsigned int num_args = e->This.u2.num_args;
1180 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1181
1182 unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1183 q.type = 'M';
1184
1185 // res
1186 struct zval *z = (struct zval *) e + s; s++;
1187 php_zval_dump(" res: ", z);
1188 q.res = z->value.p;
1189
1190 // mode
1191 if (num_args >= 2) {
1192 z = (struct zval *) e + s; s++;
1193 q.mode = z->value.lval;
1194 xlog(50, " mode=0x%lx\n", q.mode);
1195 } else {
1196 q.mode = 2; // MYSQLI_NUM
1197 }
1198
1199 ninedogs_process_db("mysqli_fetch_all", NINEDOGS_DB_FETCH_START, &q);
1200 void *ret = old_mysqli_fetch_all(e, retv);
1201 if (!retv)
1202 return ret;
1203 php_zval_dump(" retv: ", retv);
1204
1205 if (retv->u1.v.type == 7) { // array
1206 struct zend_array *a = retv->value.arr;
1207 q.num = a->nNumUsed;
1208 //q.ret = 0;
1209 // TODO php_mysqli_set_last_error(e, dbh, &qs); // TODO is qs.res set here?
1210 // TODO: do we set num and aff?
1211 } else if (retv->u1.v.type == 3) { // true (for queries not returning rows)
1212 q.num = 0;
1213 //q.ret = 1;
1214 }
1215
1216 ninedogs_process_db("mysqli_fetch_all", NINEDOGS_DB_FETCH_END, &q);
1217
1218 return ret;
1219 }
1220
1221 void *(*old_mysqli_fetch_array)(struct zend_execute_data *, struct zval *);
1222 static void *my_mysqli_fetch_array(struct zend_execute_data *e, struct zval *retv)
1223 {
1224 struct query q;
1225
1226 unsigned int num_args = e->This.u2.num_args;
1227 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1228
1229 unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1230 q.type = 'M';
1231
1232 // res
1233 struct zval *z = (struct zval *) e + s; s++;
1234 php_zval_dump(" res: ", z);
1235 q.res = z->value.p;
1236
1237 // mode
1238 if (num_args >= 2) {
1239 z = (struct zval *) e + s; s++;
1240 q.mode = z->value.lval;
1241 xlog(50, " mode=0x%lx\n", q.mode);
1242 } else {
1243 q.mode = 3; // MYSQLI_BOTH
1244 }
1245
1246 ninedogs_process_db("mysqli_fetch_array", NINEDOGS_DB_FETCH_START, &q);
1247 void *ret = old_mysqli_fetch_array(e, retv);
1248 if (!retv)
1249 return ret;
1250 php_zval_dump(" retv: ", retv);
1251
1252 if (retv->u1.v.type == 7) { // array
1253 q.ret = 2;
1254 } else if (retv->u1.v.type == 2) { // false - TODO set error
1255 q.ret = 1;
1256 } else {
1257 q.ret = 0;
1258 }
1259
1260 ninedogs_process_db("mysqli_fetch_array", NINEDOGS_DB_FETCH_END, &q);
1261
1262 return ret;
1263 }
1264
1265 void *(*old_mysqli_free_result)(struct zend_execute_data *, struct zval *);
1266 static void *my_mysqli_free_result(struct zend_execute_data *e, struct zval *retv)
1267 {
1268 struct free_result fr;
1269
1270 unsigned int num_args = e->This.u2.num_args;
1271 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1272
1273 unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1274 fr.type = 'M';
1275
1276 // res
1277 struct zval *z = (struct zval *) e + s; s++;
1278 php_zval_dump(" res: ", z);
1279 fr.res = z->value.p;
1280
1281 void *ret = old_mysqli_free_result(e, retv);
1282 if (!retv)
1283 return ret;
1284
1285 fr.ok = 1;
1286 ninedogs_process_db("mysqli_free_result", NINEDOGS_DB_FREE_RESULT, &fr);
1287
1288 return ret;
1289 }
1290
1291 void *(*old_mysqli_stmt_execute)(struct zend_execute_data *, struct zval *);
1292 static void *my_mysqli_stmt_execute(struct zend_execute_data *e, struct zval *retv)
1293 {
1294 struct execute ex;
1295
1296 unsigned int num_args = e->This.u2.num_args;
1297 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1298
1299 unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1300 ex.type = 'M';
1301 ex.params.len = 0;
1302
1303 // res
1304 struct zval *z = (struct zval *) e + s; s++;
1305 php_zval_dump(" stmt: ", z);
1306 ex.stmt = z->value.p;
1307
1308 if (num_args >= 2) {
1309 z = (struct zval *) e + s; s++;
1310 struct zend_array *za = z->value.arr;
1311 zend_array_to_params_array(&ex.params, za);
1312 }
1313
1314 ninedogs_process_db("mysqli_stmt_execute", NINEDOGS_DB_EXECUTE_START, &ex);
1315 void *ret = old_mysqli_stmt_execute(e, retv);
1316 if (!retv)
1317 return ret;
1318
1319 if (retv->u1.v.type == 3) { // true
1320 ex.ret = 1;
1321 } else if (retv->u1.v.type == 2) { // false
1322 ex.ret = 0;
1323 }
1324
1325 ninedogs_process_db("mysqli_stmt_execute", NINEDOGS_DB_EXECUTE_END, &ex);
1326
1327 return ret;
1328 }
1329
1330 void *(*old_mysqli_prepare)(struct zend_execute_data *, struct zval *);
1331 static void *my_mysqli_prepare(struct zend_execute_data *e, struct zval *retv)
1332 {
1333 struct prepare p;
1334
1335 unsigned int num_args = e->This.u2.num_args;
1336 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1337
1338 unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1339 p.type = 'M';
1340
1341 // link
1342 struct zval *z = (struct zval *) e + s; s++;
1343 php_zval_dump(" link: ", z);
1344 p.dbh = z->value.p;
1345
1346 // query
1347 z = (struct zval *) e + s; s++;
1348 struct zend_string *xs = z->value.str;
1349 xlog(50, " query=%s\n", xs->val);
1350 p.q = xs->val;
1351 p.q_len = xs->len;
1352
1353 ninedogs_process_db("mysqli_prepare", NINEDOGS_DB_PREPARE_START, &p);
1354 void *ret = old_mysqli_prepare(e, retv);
1355 if (!retv)
1356 return ret;
1357 php_zval_dump(" retv: ", retv);
1358
1359 // PHP7 returns resource, PHP8.1 returns object
1360 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) {
1361 p.stmt = retv->value.p;
1362 } else if (retv->u1.v.type == 2) { // false
1363 p.stmt = NULL;
1364 }
1365
1366 ninedogs_process_db("mysqli_prepare", NINEDOGS_DB_PREPARE_END, &p);
1367
1368 return ret;
1369 }
1370
1371 void *(*old_mysqli_stmt_prepare)(struct zend_execute_data *, struct zval *);
1372 static void *my_mysqli_stmt_prepare(struct zend_execute_data *e, struct zval *retv)
1373 {
1374 struct prepare p;
1375
1376 unsigned int num_args = e->This.u2.num_args;
1377 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1378
1379 unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1380 p.type = 'M';
1381
1382 // stmt
1383 struct zval *z = (struct zval *) e + s; s++;
1384 php_zval_dump(" stmt: ", z);
1385 p.stmt = z->value.p;
1386
1387 // query
1388 z = (struct zval *) e + s; s++;
1389 struct zend_string *xs = z->value.str;
1390 xlog(50, " query=%s\n", xs->val);
1391 p.q = xs->val;
1392 p.q_len = xs->len;
1393
1394 ninedogs_process_db("mysqli_stmt_prepare", NINEDOGS_DB_PREPARE_START, &p);
1395 void *ret = old_mysqli_stmt_prepare(e, retv);
1396 if (!retv)
1397 return ret;
1398 php_zval_dump(" retv: ", retv);
1399
1400 if (retv->u1.v.type == 3) { // true
1401 p.ret = 1;
1402 } else if (retv->u1.v.type == 2) { // false
1403 p.ret = 0;
1404 }
1405
1406 ninedogs_process_db("mysqli_stmt_prepare", NINEDOGS_DB_PREPARE_END, &p);
1407
1408 return ret;
1409 }
1410
1411 void *(*old_mysqli_autocommit)(struct zend_execute_data *, struct zval *);
1412 static void *my_mysqli_autocommit(struct zend_execute_data *e, struct zval *retv)
1413 {
1414 struct db_autocommit a;
1415
1416 unsigned int num_args = e->This.u2.num_args;
1417 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1418
1419 unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1420 a.type = 'M';
1421
1422 // link
1423 struct zval *z = (struct zval *) e + s; s++;
1424 a.link = z->value.p;
1425
1426 z = (struct zval *) e + s; s++;
1427 php_zval_dump(" bool: ", z);
1428 a.value = z->u1.v.type == 3;
1429
1430 ninedogs_process_db("mysqli_autocommit", NINEDOGS_DB_AUTOCOMMIT_START, &a);
1431 void *ret = old_mysqli_autocommit(e, retv);
1432 if (!retv)
1433 return ret;
1434
1435 if (retv->u1.v.type == 3) { // true
1436 a.ret = 1;
1437 } else if (retv->u1.v.type == 2) { // false
1438 a.ret = 0;
1439 }
1440
1441 ninedogs_process_db("mysqli_autocommit", NINEDOGS_DB_AUTOCOMMIT_END, &a);
1442
1443 return ret;
1444 }
1445
1446
1175 1447
1176 1448 struct zend_module_entry *(*old_get_module)(void); struct zend_module_entry *(*old_get_module)(void);
1177 1449 static struct zend_module_entry *php_hook_get_module_func(void) static struct zend_module_entry *php_hook_get_module_func(void)
 
... ... static struct zend_module_entry *php_hook_get_module_func(void)
1226 1498
1227 1499 fe = new->functions; fe = new->functions;
1228 1500 while (fe && fe->fname) { while (fe && fe->fname) {
1229 xlog(2, " fe=%p\n", fe);
1230 1501 xlog(100, " func %s handler=%p\n", fe->fname, fe->handler); xlog(100, " func %s handler=%p\n", fe->fname, fe->handler);
1231 1502 if (strncmp(fe->fname, "pg_", 3) == 0) { if (strncmp(fe->fname, "pg_", 3) == 0) {
1232 1503 if (strcmp(fe->fname, "pg_close") == 0) { if (strcmp(fe->fname, "pg_close") == 0) {
 
... ... static struct zend_module_entry *php_hook_get_module_func(void)
1268 1539 xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname); xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
1269 1540 } }
1270 1541 } else if (strncmp(fe->fname, "mysqli_", 7) == 0) { } else if (strncmp(fe->fname, "mysqli_", 7) == 0) {
1271 if (strcmp(fe->fname, "mysqli_close") == 0) {
1542 if (strcmp(fe->fname, "mysqli_autocommit") == 0) {
1543 old_mysqli_autocommit = fe->handler;
1544 fe->handler = my_mysqli_autocommit;
1545 } else if (strcmp(fe->fname, "mysqli_close") == 0) {
1272 1546 old_mysqli_close = fe->handler; old_mysqli_close = fe->handler;
1273 1547 fe->handler = my_mysqli_close; fe->handler = my_mysqli_close;
1274 1548 } else if (strcmp(fe->fname, "mysqli_connect") == 0) { } else if (strcmp(fe->fname, "mysqli_connect") == 0) {
1275 1549 old_mysqli_connect = fe->handler; old_mysqli_connect = fe->handler;
1276 1550 fe->handler = my_mysqli_connect; fe->handler = my_mysqli_connect;
1551 } else if (strcmp(fe->fname, "mysqli_fetch_all") == 0) {
1552 old_mysqli_fetch_all = fe->handler;
1553 fe->handler = my_mysqli_fetch_all;
1554 } else if (strcmp(fe->fname, "mysqli_fetch_array") == 0) {
1555 old_mysqli_fetch_array = fe->handler;
1556 fe->handler = my_mysqli_fetch_array;
1557 } else if (strcmp(fe->fname, "mysqli_free_result") == 0) {
1558 old_mysqli_free_result = fe->handler;
1559 fe->handler = my_mysqli_free_result;
1277 1560 } else if (strcmp(fe->fname, "mysqli_query") == 0) { } else if (strcmp(fe->fname, "mysqli_query") == 0) {
1278 1561 old_mysqli_query = fe->handler; old_mysqli_query = fe->handler;
1279 1562 fe->handler = my_mysqli_query; fe->handler = my_mysqli_query;
1563 } else if (strcmp(fe->fname, "mysqli_prepare") == 0) {
1564 old_mysqli_prepare = fe->handler;
1565 fe->handler = my_mysqli_prepare;
1280 1566 } else if (strcmp(fe->fname, "mysqli_real_connect") == 0) { } else if (strcmp(fe->fname, "mysqli_real_connect") == 0) {
1281 1567 old_mysqli_real_connect = fe->handler; old_mysqli_real_connect = fe->handler;
1282 1568 fe->handler = my_mysqli_real_connect; fe->handler = my_mysqli_real_connect;
1569 } else if (strcmp(fe->fname, "mysqli_stmt_execute") == 0) {
1570 old_mysqli_stmt_execute = fe->handler;
1571 fe->handler = my_mysqli_stmt_execute;
1572 } else if (strcmp(fe->fname, "mysqli_stmt_prepare") == 0) {
1573 old_mysqli_stmt_prepare = fe->handler;
1574 fe->handler = my_mysqli_stmt_prepare;
1283 1575 } else { } else {
1284 1576 xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname); xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
1285 1577 } }
File agent/process_db.c changed (mode: 100644) (index 3ff15d3..8d20f2f)
... ... void ninedogs_process_db(const char *func, const unsigned int type, void *d)
337 337 conn_tail = cn; conn_tail = cn;
338 338 } }
339 339 cs->cn = cn; cs->cn = cn;
340 //my_trace(func, 'c', cn->conn_str, cn->conn_str_len);
341 340 my_trace(func, 'c', cs); my_trace(func, 'c', cs);
342 341 break; break;
343 342
 
... ... void ninedogs_process_db(const char *func, const unsigned int type, void *d)
359 358 cn->max = elap; cn->max = elap;
360 359 last_db_handle = cn; last_db_handle = cn;
361 360 // TODO: if cs->dbh is null, there is an error! // TODO: if cs->dbh is null, there is an error!
362 //my_trace(func, 'r', cn->conn_str, cn->conn_str_len, cn->handle);
363 361 my_trace(func, 'r', cs); my_trace(func, 'r', cs);
364 362 break; break;
365 363
 
... ... void ninedogs_process_db(const char *func, const unsigned int type, void *d)
369 367 if (last_db_handle == cs) if (last_db_handle == cs)
370 368 last_db_handle = NULL; last_db_handle = NULL;
371 369
372 my_trace(func, 'r', cs->dbh); // TODO pass only cs
370 my_trace(func, 'R', cs);
373 371 break; break;
374 372
375 373 case NINEDOGS_DB_QUERY_START: case NINEDOGS_DB_QUERY_START:
 
... ... void ninedogs_process_db(const char *func, const unsigned int type, void *d)
443 441 cn->qt = qn; cn->qt = qn;
444 442 } }
445 443 qs->qn = qn; qs->qn = qn;
446 //my_trace(func, 'c', qs->dbh, qn->query, qn->query_len,
447 // qs->params_len, qs->params);
448 444 my_trace(func, 'c', qs); my_trace(func, 'c', qs);
449 445 break; break;
450 446
 
... ... void ninedogs_process_db(const char *func, const unsigned int type, void *d)
475 471 xlog(100, " set qn->last_start from qs->start\n"); xlog(100, " set qn->last_start from qs->start\n");
476 472 qn->last_start = qs->start; qn->last_start = qs->start;
477 473 } }
478 //my_trace(func, 'r', qs->dbh, qn->query, qn->query_len,
479 // qn->res, qs->num, qs->aff);
480 474 my_trace(func, 'r', qs); my_trace(func, 'r', qs);
481 475 break; break;
482 476
477 case NINEDOGS_DB_FETCH_START:
478 qs = (struct query *) d;
479 my_trace(func, 'c', qs);
480 break;
481
482 case NINEDOGS_DB_FETCH_END:
483 qs = (struct query *) d;
484 my_trace(func, 'r', qs);
485 break;
486
487 case NINEDOGS_DB_PREPARE_START:
488 my_trace(func, 'c', (struct prepare *) d);
489 break;
490
491 case NINEDOGS_DB_PREPARE_END:
492 my_trace(func, 'r', (struct prepare *) d);
493 break;
494
495 case NINEDOGS_DB_EXECUTE_START:
496 my_trace(func, 'c', (struct execute *) d);
497 break;
498
499 case NINEDOGS_DB_EXECUTE_END:
500 my_trace(func, 'r', (struct execute *) d);
501 break;
502
503 case NINEDOGS_DB_AUTOCOMMIT_START:
504 my_trace(func, 'c', (struct db_autocommit *) d);
505 break;
506
507 case NINEDOGS_DB_AUTOCOMMIT_END:
508 my_trace(func, 'r', (struct db_autocommit *) d);
509 break;
510
483 511 case NINEDOGS_DB_FREE_RESULT: case NINEDOGS_DB_FREE_RESULT:
484 512 struct free_result *fr = (struct free_result *) d; struct free_result *fr = (struct free_result *) d;
485 513
 
... ... void ninedogs_process_db(const char *func, const unsigned int type, void *d)
494 522 //my_time_add(&qn->process_sum, &elap); //my_time_add(&qn->process_sum, &elap);
495 523
496 524 qn->res = NULL; qn->res = NULL;
497 my_trace(func, 'r', fr->res, fr->ok);
525 my_trace(func, 'R', fr);
498 526 break; break;
499 527 } }
500 528
File agent/process_db.h changed (mode: 100644) (index 9ee28cd..05e0db3)
... ... struct conn
19 19 #define ND_PARAMS_TYPE_LONG 1 #define ND_PARAMS_TYPE_LONG 1
20 20 #define ND_PARAMS_TYPE_DOUBLE 2 #define ND_PARAMS_TYPE_DOUBLE 2
21 21 #define ND_PARAMS_TYPE_STRING 3 #define ND_PARAMS_TYPE_STRING 3
22 struct params_array
22 struct params_array_one
23 23 { {
24 24 unsigned char type; // see ND_PARAMS_TYPE_* unsigned char type; // see ND_PARAMS_TYPE_*
25 25 unsigned char pad1; unsigned char pad1;
26 unsigned short length;
26 unsigned short length; // for 'str'
27 27 unsigned char pad2[4]; unsigned char pad2[4];
28 28 union { union {
29 29 char *str; char *str;
 
... ... struct params_array
32 32 }; };
33 33 }; };
34 34
35 struct params_array
36 {
37 unsigned short len;
38 unsigned short pad[3];
39 struct params_array_one list[ND_PARAMS_MAX];
40 };
41
35 42 struct query struct query
36 43 { {
37 44 void *cn; // this is used in process_db void *cn; // this is used in process_db
38 45 void *qn; // this is used in process_db void *qn; // this is used in process_db
39 struct params_array params[ND_PARAMS_MAX]; // this is used in process_db
46 struct params_array params; // this is used in process_db
40 47 char type; char type;
41 char pad1[3];
48 char ret; // used at least by mysqli_fetch_array
49 char pad1[2];
50 unsigned short err_len, err_code_len;
42 51 unsigned int q_len; unsigned int q_len;
52 unsigned int pad2;
43 53 void *dbh; void *dbh;
44 54 struct timeval start, end; struct timeval start, end;
45 55 char *q; char *q;
46 unsigned short err_len, err_code_len;
47 unsigned int params_len;
48 56 char *err, *err_code; char *err, *err_code;
49 unsigned long num, aff;
57 unsigned long num, aff, mode; // 'mode' is used by mysql
50 58 void *res; void *res;
51 59 }; };
52 60
 
... ... struct free_result
59 67 void *res; void *res;
60 68 }; };
61 69
70 struct prepare
71 {
72 char *q;
73 char type;
74 char ret;
75 char pad[2];
76 unsigned int q_len;
77 void *dbh;
78 void *stmt;
79 };
80
81 struct execute
82 {
83 void *stmt;
84 struct params_array params; // this is used in process_db
85 char type;
86 char ret;
87 char pad1[6];
88 };
89
90 struct db_autocommit
91 {
92 void *link;
93 char type;
94 char value;
95 char ret;
96 char pad1[5];
97 };
98
62 99 void query_send_string(const unsigned char *hash); void query_send_string(const unsigned char *hash);
63 100
64 101 void ninedogs_process_db(const char *func, const unsigned int type, void *d); void ninedogs_process_db(const char *func, const unsigned int type, void *d);
File agent/python.c changed (mode: 100644) (index fe40f5d..e08913e)
... ... static void zend_array_to_params_array(struct query *q, struct zend_array *za)
317 317 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize,
318 318 za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : ""); za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : "");
319 319
320 max = za->nNumUsed;
321 if (max > ND_PARAMS_MAX)
322 max = ND_PARAMS_MAX;
320 q->params.len = za->nNumUsed;
321 if (q->params.len > ND_PARAMS_MAX)
322 q->params.len = ND_PARAMS_MAX;
323 323
324 324 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed; struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
325 325 for (; bs != be; bs++) { for (; bs != be; bs++) {
 
... ... static void zend_array_to_params_array(struct query *q, struct zend_array *za)
343 343 bs, bs->h, zs, python_get_type(_z), python_get_value(_z)); bs, bs->h, zs, python_get_type(_z), python_get_value(_z));
344 344
345 345 if (_z->u1.v.type == 4) { if (_z->u1.v.type == 4) {
346 q->params[i].type = ND_PARAMS_TYPE_LONG;
347 q->params[i].l = _z->value.lval;
346 q->params.list[i].type = ND_PARAMS_TYPE_LONG;
347 q->params.list[i].l = _z->value.lval;
348 348 } else if (_z->u1.v.type == 5) { } else if (_z->u1.v.type == 5) {
349 q->params[i].type = ND_PARAMS_TYPE_DOUBLE;
350 q->params[i].d = _z->value.dval;
349 q->params.list[i].type = ND_PARAMS_TYPE_DOUBLE;
350 q->params.list[i].d = _z->value.dval;
351 351 } else if (_z->u1.v.type == 6) { } else if (_z->u1.v.type == 6) {
352 q->params[i].type = ND_PARAMS_TYPE_STRING;
352 q->params.list[i].type = ND_PARAMS_TYPE_STRING;
353 353 struct zend_string *zs = _z->value.str; struct zend_string *zs = _z->value.str;
354 q->params[i].str = zs->val;
355 q->params[i].length = zs->len;
354 q->params.list[i].str = zs->val;
355 q->params.list[i].length = zs->len;
356 356 } }
357 357
358 358 i++; i++;
359 359 if (i == max) if (i == max)
360 360 break; break;
361 361 } }
362
363 q->params_len = za->nNumUsed;
364 362 } }
365 363
366 364 void *(*old_python_pg_last_error)(struct zend_execute_data *, struct zval *); void *(*old_python_pg_last_error)(struct zend_execute_data *, struct zval *);
 
... ... static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
621 619 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
622 620 para = (struct zval *) e + s; para = (struct zval *) e + s;
623 621 qs.type = 'P'; // if dbh is null, we do not know the type qs.type = 'P'; // if dbh is null, we do not know the type
624 qs.params_len = 0;
622 qs.params.len = 0;
625 623
626 624 if (num_args == 2) { if (num_args == 2) {
627 625 // link // link
 
... ... static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv)
681 679
682 680 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
683 681 qs.type = 'P'; qs.type = 'P';
684 qs.params_len = 0;
682 qs.params.len = 0;
685 683
686 684 // link // link
687 685 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
 
... ... static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv)
733 731 para = (struct zval *) e + s; para = (struct zval *) e + s;
734 732 qs.type = 'P'; qs.type = 'P';
735 733 qs.q = NULL; qs.q = NULL;
736 qs.params_len = 0;
734 qs.params.len = 0;
737 735
738 736 // link // link
739 737 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
File common/ids.h changed (mode: 100644) (index 901db92..468841d)
... ... enum
49 49 NINEDOGS_DB_QUERY_END, NINEDOGS_DB_QUERY_END,
50 50 NINEDOGS_DB_FREE_RESULT, NINEDOGS_DB_FREE_RESULT,
51 51 NINEDOGS_DB_CONN_CLOSE, NINEDOGS_DB_CONN_CLOSE,
52 NINEDOGS_DB_FETCH_START,
53 NINEDOGS_DB_FETCH_END,
54 NINEDOGS_DB_PREPARE_START,
55 NINEDOGS_DB_PREPARE_END,
56 NINEDOGS_DB_EXECUTE_START,
57 NINEDOGS_DB_EXECUTE_END,
58 NINEDOGS_DB_AUTOCOMMIT_START,
59 NINEDOGS_DB_AUTOCOMMIT_END,
52 60 NINEDOGS_DB_MAX // this must be last NINEDOGS_DB_MAX // this must be last
53 61 }; };
54 62
File docs/.gitignore added (mode: 100644) (index 0000000..668c26b)
1 *.aux
2 *.toc
3 *.vrb
4 *.snm
5 *.nav
6 *.pdf
File docs/Makefile added (mode: 100644) (index 0000000..0813d5d)
1 all: pre1.pdf
2
3 pre1.pdf: pre1.tex
4 pdflatex $<
5
File docs/pre1.tex added (mode: 100644) (index 0000000..8207e00)
1 \documentclass[10pt]{beamer}
2
3 \usetheme{default}
4
5 \usepackage[english]{babel}
6 \usepackage{hyperref}
7 \usepackage{url}
8 \usepackage[utf8]{inputenc}
9
10 \title{ninedogs project introduction}
11 \subtitle{ninedogs workshop for Devs and DevOps (tracing)}
12 \author{Catalin(ux) M. BOIE}
13 \date{2022-11-09}
14 %\titlegraphic{\includegraphics[width=2.5cm]{ninedogs.svg}}
15
16
17 \begin{document}
18
19 \begin{frame}
20 \titlepage
21 \end{frame}
22
23 \begin{frame}{Outline}
24 \tableofcontents
25 \end{frame}
26
27 \section{Introduction}
28
29 \subsection{What, how, why?}
30
31 \begin{frame}
32 \begin{block}{What is ninedogs?}
33 \begin{itemize}
34 \item A set of tools helping the Developers, database/system admins and DevOps
35 to get more information from the running processes.
36 \item A client/server application streaming tracing information to the server
37 for later analysis.
38 \item A log collection tool (future).
39 \item An alerting tool for certificate imminent expiration and security issues alerting.
40 \item A tool for live patching of applications (Log4J etc.).
41 \end{itemize}
42 \end{block}
43 \end{frame}
44
45 \begin{frame}
46 \begin{block}{How ninedogs is working?}
47 \begin{itemize}
48 \item It uses LD\_PRELOAD mechanism to hook all interesting shared libraries calls.
49 \item Examples of hooked funtions (not syscalls! it does not use ptrace): recv, send, open,
50 mysqli\_fetch\_array, pg\_pconnect, sqlite3\_open\_v2, syslog etc.
51 \item Many more will come in each release.
52 \end{itemize}
53 \end{block}
54 \end{frame}
55
56 \begin{frame}
57 \begin{block}{Why strace/ltrace are not good enough?}
58 \begin{itemize}
59 \item They cannot be used in GCP and Azure (probably also AWS) containers for
60 security reasons.
61 \item They are low level tools; e.g. if a connection to a database is encrypted,
62 you cannot see anything interesting.
63 \item They are way too verbose.
64 \end{itemize}
65 \end{block}
66 \end{frame}
67
68
69 \subsection{Preparations for using ninedogs tracing}
70
71 \begin{frame}
72 \begin{block}{Installation}
73 \begin{itemize}
74 \item With the help of https://rocketgit.com, we build ninedogs for a lot of
75 distributions and architectures.
76 Check \href{https://rocketgit.com/op/pkg_repos}{https://rocketgit.com/op/pkg\_repos}
77 to see if your distro/arch is supported. Ask if not there.
78 \item ninedogs can be installed both in a normal Linux distribution or in a container.
79 \end{itemize}
80 \end{block}
81 \end{frame}
82
83
84 \section{Demo}
85
86 \subsection{Real life examples}
87
88
89 \begin{frame}[fragile]{MySQL connection}
90 \begin{block}{strace}
91 \tiny
92 \begin{verbatim}
93 socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 5
94 fcntl(5, F_GETFL) = 0x2 (flags O_RDWR)
95 fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK) = 0
96 connect(5, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("x.x.x.x")},16)
97 = -1 EINPROGRESS (Operation now in progress)
98 poll([{fd=5, events=POLLIN\|POLLOUT\|POLLERR\|POLLHUP}], 1, 60000) = 1 ([{fd=5, revents=POLLOUT}])
99 getsockopt(5, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
100 fcntl\(5, F_SETFL, O_RDWR\) = 0
101 setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0
102 setsockopt(5, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
103 poll([{fd=5, events=POLLIN|POLLERR|POLLHUP}], 1, 86400000) = 1 ([{fd=5, revents=POLLIN}])
104 recvfrom(5, "Y\0\0\0\n5.5.5-10.5.16-MariaDB...", 32768, MSG_DONTWAIT, NULL, NULL) = 93
105 sendto(5, "\203\0\0\1\315...", 135, MSG_DONTWAIT, NULL, 0) = 135
106 poll([{fd=5, events=POLLIN|POLLERR|POLLHUP}], 1, 86400000) = 1 ([{fd=5, revents=POLLIN}])
107 recvfrom(5, "\7\0\0\2\0\0\0\2\0\0\0", 32768, MSG_DONTWAIT, NULL, NULL) = 11}
108 \end{verbatim}
109 \end{block}
110
111 \begin{block}{nd-trace}
112 \tiny
113 \begin{verbatim}
114 mysqli_real_connect(link=0x7fc52127f010, 'host=h1 user=ninedogs port=3306 db=ninedogs socket=',
115 flags='0x40|SSL_DONT_VERIFY_SERVER_CERT')
116 [strace like output (connect/poll/recvfrom/sendto etc.) ommited]
117 mysqli_real_connect(link=0x7fc52127f010, 'host=h1 user=ninedogs port=3306 db=ninedogs socket=',
118 flags='0x40|SSL_DONT_VERIFY_SERVER_CERT') = ok
119 \end{verbatim}
120 \end{block}
121 \end{frame}
122
123
124 \begin{frame}[fragile]{sqlite3}
125 \begin{block}{strace}
126 \tiny
127 \begin{verbatim}
128 openat(AT_FDCWD, "/date/sync/no-crypt/sync1/Dev/ninedogs/test/python/sqlite1.db",
129 O_RDWR|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0644) = 3
130 pread64(3, "SQLite format 3...", 100, 0) = 100
131 fcntl(3, F_SETLK, {l_type=F_RDLCK, l_whence=SEEK_SET, l_start=1073741824, l_len=1}) = 0
132 [lots of pread64/pwrite64/fcntl removed]
133 pwrite64(3, "...\0\16\1\3\t#first_value", 4096, 4096) = 4096
134 \end{verbatim}
135 \end{block}
136
137 \begin{block}{nd-trace}
138 \tiny
139 \begin{verbatim}
140 sqlite3_open_v2('sqlite1.db', 0x6|READWRITE|CREATE, '')
141 sqlite3_open_v2('sqlite1.db', 0x55c13dfba5a8, 0x6|READWRITE|CREATE, '') = OK
142 sqlite3_prepare_v2(0x55794910b5a8, 'INSERT INTO test1 VALUES (:id, :val);', -1, stmt, tail)
143 sqlite3_prepare_v2(0x55794910b5a8, 'INSERT INTO test1 VALUES (:id, :val);', -1, 0x55794918e388, tail) = OK
144 sqlite3_bind_int64(stmt=0x5594c1d78388, index=1, value=1) = OK
145 sqlite3_bind_text(stmt=0x55d53848e388, index=2, 'first_value') = OK
146 sqlite3_step(0x5594c1d78388)
147 sqlite3_step(0x5594c1d78388) = DONE
148 sqlite3_finalize(0x5594c1d78388) = OK
149 \end{verbatim}
150 \end{block}
151 \end{frame}
152
153
154 \begin{frame}[fragile]{Hostname resolving}
155 \begin{block}{strace}
156 \tiny
157 \begin{verbatim}
158 socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) = 20
159 fcntl(20, F_GETFL) = 0x2 (flags O_RDWR)
160 fcntl(20, F_SETFL, O_RDWR|O_NONBLOCK) = 0
161 setsockopt(20, SOL_SOCKET, SO_TIMESTAMP_OLD, [1], 4) = 0
162 setsockopt(20, SOL_IP, IP_RECVTOS, [1], 4) = 0
163 setsockopt(20, SOL_IP, IP_MTU_DISCOVER, [5], 4) = 0
164 epoll_ctl(13, EPOLL_CTL_ADD, 20, {events=EPOLLIN, data={u32=20, u64=20}}) = 0
165 sendmsg(20, {msg_name={sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")},
166 msg_namelen=16, msg_iov=[{iov_base="iD\1\0\0\1\0\0\0\0\0\0\3bla\6comcom\3com\0\0\1\0\1",
167 iov_len=32}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 32
168 recvmsg(20, {msg_name={sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")},
169 msg_namelen=128 => 16, msg_iov=[{iov_base="iD\201\203\0\1\0\0\0\1\0\0\3bla\6comcom\3com\0\0\1\0\1\300
170 \20\0\6\0\1\0\0\2X\0:\6pdns09\rdomaincontrol\300\27\3dns\5jomax\3net\0xg\214\350\0\0p\200\0\0\34 \0
171 \t:\200\0\0\2X", iov_len=65535}], msg_iovlen=1, msg_control=[{cmsg_len=32, cmsg_level=SOL_SOCKET,
172 cmsg_type=SO_TIMESTAMP_OLD, cmsg_data={tv_sec=1668197537, tv_usec=794128}}, {cmsg_len=17,
173 cmsg_level=SOL_IP, cmsg_type=IP_TOS, cmsg_data=[0]}], msg_controllen=56, msg_flags=0}, 0) = 102
174 epoll_ctl(13, EPOLL_CTL_DEL, 20, 0x7f43aa4aaa04) = 0
175 close(20)
176 \end{verbatim}
177 \end{block}
178
179 \begin{block}{nd-trace}
180 \tiny
181 \begin{verbatim}
182 gethostbyname_r('bla.com.com.com')
183 gethostbyname_r('bla2.com.com.com') => name=[bla2.com.com.com] aliases={} addrs={45.33.20.235, 173.255.194.134}
184 \end{verbatim}
185 \end{block}
186 \end{frame}
187
188
189 \section{Other interesting things}
190
191 \begin{frame}[fragile]{Segmentation fault}
192 \begin{block}{strace}
193 \tiny
194 \begin{verbatim}
195 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} ---
196 +++ killed by SIGSEGV (core dumped) +++
197 Segmentation fault (core dumped)
198 \end{verbatim}
199 \end{block}
200
201 \begin{block}{nd-trace}
202 \tiny
203 \begin{verbatim}
204 -segv: ../../agent/ninedogs.so(+0x11032) [0x7fc0f524a032]
205 /lib64/libc.so.6(+0x3ea30) [0x7fc0f503ea30]
206 ./segv() [0x401149]
207 /lib64/libc.so.6(+0x29510) [0x7fc0f5029510]
208 /lib64/libc.so.6(__libc_start_main+0x89) [0x7fc0f50295c9]
209 ./segv() [0x401065]
210 \end{verbatim}
211 \end{block}
212 \end{frame}
213
214
215 \begin{frame}[fragile]{bla - no tiny}
216 \begin{block}{}
217 \tiny
218 \begin{verbatim}
219 \end{verbatim}
220 \end{block}
221
222 \begin{block}{ - nd-trace}
223 \tiny
224 \begin{verbatim}
225 text
226 \end{verbatim}
227 \end{block}
228 \end{frame}
229
230
231 \end{document}
232
File docs/pre1.txt changed (mode: 100644) (index 082d50e..df692d4)
1 1 Ideas for the first presentation Ideas for the first presentation
2 2
3 - Who is the target of the prezentation.
4 - Why?
3 5 - Difference between strace and nd-trace - Difference between strace and nd-trace
4 6 - Why strace cannot be used in cloud in containers - Why strace cannot be used in cloud in containers
5 7 - Talk about high-level decoding - Talk about high-level decoding
6 8 - Show some examples - Show some examples
9 - Performance impact
7 10 - -
File test/dotnet/a1/1.run changed (mode: 100755) (index 9ec2e3e..54a4802)
1 1 #!/bin/bash #!/bin/bash
2 2
3 set -e
4
5 3 dotnet build dotnet build
6 4
7 5 export LD_PRELOAD=../../../agent/ninedogs.so export LD_PRELOAD=../../../agent/ninedogs.so
 
... ... export LD_PRELOAD=../../../agent/ninedogs.so
9 7 export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
10 8 export NINEDOGS_SERVER_PORT=36000 export NINEDOGS_SERVER_PORT=36000
11 9 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552
12 export NINEDOGS_VERBOSE=400
10 export NINEDOGS_VERBOSE=40
13 11 export NINEDOGS_SYNC_FLUSH=1 export NINEDOGS_SYNC_FLUSH=1
14 12
15 export NINEDOGS_VERBOSE=100
16 13 #export LD_DEBUG=all #export LD_DEBUG=all
17 14 export LD_DEBUG_OUTPUT=1.ld.txt export LD_DEBUG_OUTPUT=1.ld.txt
18 15
16 echo "Running..."
19 17 #ltrace -s200 -f -tt -S -o 1.ltrace \ #ltrace -s200 -f -tt -S -o 1.ltrace \
20 18 #strace -tt -f -s2000 -o 1.strace \ #strace -tt -f -s2000 -o 1.strace \
21 dotnet run 2>&1 | LD_PRELOAD= LD_DEBUG= tee 1.out
19 #DEBUGINFOD_URLS= valgrind -v --trace-children=yes \
20 #dotnet run 2>&1 | LD_PRELOAD= LD_DEBUG= tee 1.out
22 21
22 dotnet run &> 1.out &
23 LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace -o 1.nd -p ${!}
23 24
File test/dotnet/a1/Program.cs changed (mode: 100644) (index a824c19..f39d3a4)
... ... using var con = new NpgsqlConnection(cs);
7 7 Console.WriteLine("Connecting..."); Console.WriteLine("Connecting...");
8 8 con.Open(); con.Open();
9 9
10 Thread.Sleep(10 * 1000);
10 Thread.Sleep(1 * 1000);
11 11
12 12 Console.WriteLine("Selecting..."); Console.WriteLine("Selecting...");
13 13 var sql = "SELECT version()"; var sql = "SELECT version()";
File test/java/jdbc/1.run changed (mode: 100755) (index 793aeea..e3bb4c2)
... ... export NINEDOGS_SYNC_FLUSH=1
27 27 #strace -s20000 -f -o 1.strace \ #strace -s20000 -f -o 1.strace \
28 28 # -javaagent:../../agent/java/agent/ninedogs-agent.jar \ # -javaagent:../../agent/java/agent/ninedogs-agent.jar \
29 29 java \ java \
30 -cp /usr/share/java/postgresql-jdbc.jar:. pg1
30 -Xdiag \
31 -cp /usr/share/java/postgresql-jdbc.jar:. pg1 2>&1 | tee 1.out &
32
33 echo "Runing trace..."
34 LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace -o 1.nd -p ${!}
31 35
32 36 # ninedogs must inject this: # ninedogs must inject this:
33 37 # -javaagent:../../../agent/java/agent/ninedogs-agent.jar # -javaagent:../../../agent/java/agent/ninedogs-agent.jar
File test/java/jdbc/pg1.java changed (mode: 100644) (index fd4446c..ec3004b)
... ... public class pg1 {
16 16 c = DriverManager c = DriverManager
17 17 .getConnection("jdbc:postgresql://localhost:5432/ninedogs?ApplicationName=pg1", .getConnection("jdbc:postgresql://localhost:5432/ninedogs?ApplicationName=pg1",
18 18 "ninedogs", ""); "ninedogs", "");
19
20 19 System.err.println("Opened database successfully"); System.err.println("Opened database successfully");
21 20
22 /*
23 21 System.err.println("Query (prepared)..."); System.err.println("Query (prepared)...");
24 //System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx prepare start");
22 System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx prepare start");
25 23 PreparedStatement preparedStatement = c.prepareStatement("SELECT ? AS id"); PreparedStatement preparedStatement = c.prepareStatement("SELECT ? AS id");
26 //System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx prepare end");
24 System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx prepare end");
27 25 preparedStatement.setInt(1, 1); preparedStatement.setInt(1, 1);
28 26 System.err.println("Prepared statement: " + preparedStatement); System.err.println("Prepared statement: " + preparedStatement);
29 27
30 28 System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx execute q start"); System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx execute q start");
31 ResultSet rs = preparedStatement.executeQuery();
29 ResultSet rs1 = preparedStatement.executeQuery();
32 30 System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx execute q end"); System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx execute q end");
33 */
31 while (rs1.next()) {
32 int id = rs1.getInt("id");
33 System.err.println(" id=" + id);
34 }
34 35
36 System.err.println("");
35 37 System.err.println("Query (normal)..."); System.err.println("Query (normal)...");
36 38 Statement stmt = c.createStatement(); Statement stmt = c.createStatement();
37 ResultSet rs = stmt.executeQuery("SELECT * FROM n1 LIMIT 220");
39 ResultSet rs2 = stmt.executeQuery("SELECT * FROM n1 LIMIT 2");
38 40 System.err.println("Query (normal) done"); System.err.println("Query (normal) done");
39
40 while (rs.next()) {
41 int id = rs.getInt("id");
42 //System.err.println("id=" + id);
41 while (rs2.next()) {
42 int id = rs2.getInt("id");
43 System.err.println(" id=" + id);
43 44 } }
45 stmt.close();
44 46
47 c.close();
45 48 System.err.println("Done"); System.err.println("Done");
46 49 } catch (Exception e) { } catch (Exception e) {
47 50 e.printStackTrace(); e.printStackTrace();
File test/php-dns/1.php added (mode: 100644) (index 0000000..8a839bd)
1 <?php
2
3 echo gethostbyname('bla2.com.com.com');
4 echo gethostbyname('r1');
5 echo gethostbyname('google.com');
6
File test/php-dns/1.run copied from file test/php-mysql/1.run (similarity 94%) (mode: 100755) (index ca14455..4b7d12e)
... ... export LD_PRELOAD=../../agent/ninedogs.so
5 5 export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
6 6 export NINEDOGS_SERVER_PORT=36000 export NINEDOGS_SERVER_PORT=36000
7 7 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556
8 export NINEDOGS_VERBOSE=41
8 export NINEDOGS_VERBOSE=241
9 9 export NINEDOGS_SYNC_FLUSH=1 export NINEDOGS_SYNC_FLUSH=1
10 10
11 11 #export LD_DEBUG=all #export LD_DEBUG=all
 
... ... export LD_DEBUG_OUTPUT=1.ld.txt
13 13
14 14 export DEBUGINFOD_URLS= export DEBUGINFOD_URLS=
15 15
16 #ltrace -s200 -f -tt -S -o 1.ltrace \
17 16 #valgrind -v --trace-children=yes \ #valgrind -v --trace-children=yes \
18 17 #strace -tt -f -s2000 -o 1.strace \ #strace -tt -f -s2000 -o 1.strace \
18 #ltrace -s200 -f -tt -S -o 1.ltrace \
19 19 php 1.php &>1.out & php 1.php &>1.out &
20 20 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!} LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!}
21 21
File test/php-mysql/1.php changed (mode: 100644) (index 87c66ad..21e5b0c)
... ... for ($i = 0; $i < 4; $i++) {
23 23 } }
24 24
25 25
26 echo 'Setting char set...' . "\n";
26 echo 'Setting charset...' . "\n";
27 27 mysqli_set_charset($db, 'utf8mb4'); mysqli_set_charset($db, 'utf8mb4');
28 28
29 29
30 echo 'Setting autocommit to true...' . "\n";
31 mysqli_autocommit($db, TRUE);
32
33
30 34 try { try {
31 35 echo 'Dropping non-existing table1...' . "\n"; echo 'Dropping non-existing table1...' . "\n";
32 36 $res = @mysqli_query($db, 'DROP TABLE non_existing1'); $res = @mysqli_query($db, 'DROP TABLE non_existing1');
 
... ... if (1) {
46 50
47 51 // query without '$db' // query without '$db'
48 52 $res = mysqli_query($db, 'SELECT id FROM n1 LIMIT 1'); $res = mysqli_query($db, 'SELECT id FROM n1 LIMIT 1');
49 $rows = mysqli_fetch_all($res);
53 $row = mysqli_fetch_array($res, MYSQLI_BOTH);
50 54 mysqli_free_result($res); mysqli_free_result($res);
51 55 } }
52 56
 
... ... print_r($rows);
60 64 mysqli_free_result($res); mysqli_free_result($res);
61 65 } }
62 66
63 // query with parameters
64 echo 'Querying with parameters...' . "\n";
67 // query with parameters I
68 echo 'Querying with parameters (mysqli_prepare)...' . "\n";
65 69 $sql = 'SELECT id, a1 FROM n1 WHERE id = ? OR id = ? OR d = ? OR a1 = ? OR a1 = ?'; $sql = 'SELECT id, a1 FROM n1 WHERE id = ? OR id = ? OR d = ? OR a1 = ? OR a1 = ?';
66 70 $stmt = mysqli_prepare($db, $sql); $stmt = mysqli_prepare($db, $sql);
67 71 mysqli_stmt_bind_param($stmt, 'iidss', $a, $b, $c, $d, $e); mysqli_stmt_bind_param($stmt, 'iidss', $a, $b, $c, $d, $e);
68 72 $a = 1; $b = $a + 1; $c = 8.3; $d = 'bla'; $e = 'bla2'; $a = 1; $b = $a + 1; $c = 8.3; $d = 'bla'; $e = 'bla2';
73 mysqli_execute($stmt);
74 mysqli_execute($stmt, array('1', '2', '3', '4', '5'));
75 $res = mysqli_stmt_get_result($stmt);
76 echo 'Calling native mysqli_num_rows:' . "\n";
77 echo 'native num_rows: ' . mysqli_num_rows($res) . "\n";
78 echo 'fetching data...' . "\n";
79 $rows = mysqli_fetch_all($res);
80 print_r($rows);
81 mysqli_free_result($res);
82 mysqli_stmt_close($stmt);
83
84 // query with parameters II
85 echo 'Querying with parameters (mysqli_stmt_prepare)...' . "\n";
86 $sql = 'SELECT id, a1 FROM n1 WHERE id = ? OR id = ? OR d = ? OR a1 = ? OR a1 = ?';
87 echo 'Calling mysqli_stmt_init...' . "\n";
88 $stmt = mysqli_stmt_init($db);
89 echo 'Calling mysqli_stmt_prepare...' . "\n";
90 mysqli_stmt_prepare($stmt, $sql);
91 echo 'Calling mysqli_stmt_bind_param...' . "\n";
92 mysqli_stmt_bind_param($stmt, 'iidss', $a, $b, $c, $d, $e);
93 $a = 1; $b = $a + 1; $c = 8.3; $d = 'bla'; $e = 'bla2';
94 echo 'Calling mysqli_stmt_execute 1...' . "\n";
69 95 mysqli_stmt_execute($stmt); mysqli_stmt_execute($stmt);
96 echo 'Calling mysqli_stmt_execute 2...' . "\n";
97 mysqli_stmt_execute($stmt, array('1', '2', '3', '4', '5'));
98 echo 'Calling mysqli_stmt_get_result...' . "\n";
70 99 $res = mysqli_stmt_get_result($stmt); $res = mysqli_stmt_get_result($stmt);
71 100 echo 'Calling native mysqli_num_rows:' . "\n"; echo 'Calling native mysqli_num_rows:' . "\n";
72 101 echo 'native num_rows: ' . mysqli_num_rows($res) . "\n"; echo 'native num_rows: ' . mysqli_num_rows($res) . "\n";
File test/php-mysql/1.run changed (mode: 100755) (index ca14455..e5cbc8e)
... ... export LD_PRELOAD=../../agent/ninedogs.so
5 5 export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
6 6 export NINEDOGS_SERVER_PORT=36000 export NINEDOGS_SERVER_PORT=36000
7 7 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556
8 export NINEDOGS_VERBOSE=41
8 export NINEDOGS_VERBOSE=141
9 9 export NINEDOGS_SYNC_FLUSH=1 export NINEDOGS_SYNC_FLUSH=1
10 10
11 11 #export LD_DEBUG=all #export LD_DEBUG=all
File test/php-pg/1.run changed (mode: 100755) (index 39c80e9..ebe5353)
... ... export DEBUGINFOD_URLS=
16 16 #ltrace -s200 -f -tt -S -o 1.ltrace \ #ltrace -s200 -f -tt -S -o 1.ltrace \
17 17 #valgrind -v --trace-children=yes \ #valgrind -v --trace-children=yes \
18 18 #strace -tt -f -s2000 -o 1.strace \ #strace -tt -f -s2000 -o 1.strace \
19 php 1.php
20
19 php 1.php &>1.out &
20 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!}
File test/php-pg/free-result.sh changed (mode: 100755) (index 8dbebce..71872bc)
... ... export DEBUGINFOD_URLS=
16 16 #ltrace -s200 -f -tt -S -o free-result.ltrace \ #ltrace -s200 -f -tt -S -o free-result.ltrace \
17 17 #valgrind -v --trace-children=yes \ #valgrind -v --trace-children=yes \
18 18 #strace -tt -f -s2000 -o free-result.strace \ #strace -tt -f -s2000 -o free-result.strace \
19 php free-result.php
19 php free-result.php &>free-result.out &
20 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o free-result.nd -p ${!}
20 21
File test/php-sock/3.run changed (mode: 100755) (index a8cdd15..1b01466)
1 1 #!/bin/bash #!/bin/bash
2 2
3 export LD_PRELOAD=../../src/ninedogs.so
3 export LD_PRELOAD=../../agent/ninedogs.so
4 4
5 export FORCE_NET_VERBOSE=100
6 export LD_DEBUG=all
5 export NINEDOGS_VERBOSE=200
6 #export LD_DEBUG=all
7 7 export LD_DEBUG_OUTPUT=3.ld.txt export LD_DEBUG_OUTPUT=3.ld.txt
8 8
9 9 #strace -tt -f -s2000 -o 3.strace \ #strace -tt -f -s2000 -o 3.strace \
File test/python/sqlite1.py changed (mode: 100644) (index 7c895e2..40504ec)
... ... try:
4 4 db = sqlite3.connect('sqlite1.db') db = sqlite3.connect('sqlite1.db')
5 5 cursor = db.cursor() cursor = db.cursor()
6 6
7 print('Dropping table...')
7 print('Dropping table...', flush=True)
8 8 cursor.execute("DROP TABLE IF EXISTS test1") cursor.execute("DROP TABLE IF EXISTS test1")
9 9
10 10 table = """ CREATE TABLE test1 ( table = """ CREATE TABLE test1 (
11 id INT,
11 12 bla VARCHAR(255) bla VARCHAR(255)
12 13 ); """ ); """
13 14 cursor.execute(table) cursor.execute(table)
14 15
15 query = 'INSERT INTO test1 VALUES (:val);'
16 cursor.execute(query, { "val": "first_value"})
16 print('Inserting...', flush=True);
17 query = 'INSERT INTO test1 VALUES (:id, :val);'
18 cursor.execute(query, { "id": 1, "val": "first_value"})
17 19
20 print('Commiting...', flush=True);
18 21 db.commit() db.commit()
19 #cursor.execute("COMMIT;")
20 22
23 print('Selecting...', flush=True);
21 24 query = 'SELECT * FROM test1;' query = 'SELECT * FROM test1;'
22 25 cursor.execute(query) cursor.execute(query)
23 26 result = cursor.fetchall() result = cursor.fetchall()
24 27 print('Result is {}'.format(result)) print('Result is {}'.format(result))
25 28
29 print('Cursor closing...', flush=True);
26 30 cursor.close() cursor.close()
27 31
28 32 except sqlite3.Error as error: except sqlite3.Error as error:
 
... ... except sqlite3.Error as error:
30 34
31 35 finally: finally:
32 36 if db: if db:
37 print('DB closing...', flush=True);
33 38 db.close() db.close()
34 39
File test/segv1/1.run changed (mode: 100755) (index 0f5fd3e..8fb0b7f)
2 2
3 3 set -e set -e
4 4
5 make segv
5 gcc -g -o segv segv.c
6 6
7 7 export LD_PRELOAD=../../agent/ninedogs.so export LD_PRELOAD=../../agent/ninedogs.so
8 8
 
... ... export NINEDOGS_SYNC_FLUSH=1
15 15 #export LD_DEBUG=symbols #export LD_DEBUG=symbols
16 16 #export LD_DEBUG_OUTPUT=1.ld.txt #export LD_DEBUG_OUTPUT=1.ld.txt
17 17
18 ./segv bla1 bla2
18 ./segv bla1 bla2 &
19 ../../trace/nd-trace -o segv.nd -p ${!}
19 20
File test/segv1/segv.c changed (mode: 100644) (index badfff0..afa9ec2)
... ... int main(void)
2 2 { {
3 3 char *a = 0; char *a = 0;
4 4
5 sleep(1); // to have a chance to attach
6
5 7 return *a; return *a;
6 8 } }
File trace/TODO changed (mode: 100644) (index 0dfcde9..28e4a4e)
1 1 == Urgent == == Urgent ==
2 2 [ ] All functions must have 'c' and 'r' [ ] All functions must have 'c' and 'r'
3 Exaple: close can take a lot of time!
3 Example: close can take a lot of time!
4 4 Not all, but the ones which may wait. Not all, but the ones which may wait.
5 [ ] With multiple threads, we cannot the 'tail_new' mambo jambo!
6 5 [ ] After fork, only the parent sees "-stop"! [ ] After fork, only the parent sees "-stop"!
7 6 [ ] [ ]
8 7
File trace/nd-trace.c changed (mode: 100644) (index 03197de..4725370)
... ... static uint8_t decode_bool(const char *prefix, char *out, size_t out_size,
83 83 unsigned char *d, unsigned int *i) unsigned char *d, unsigned int *i)
84 84 { {
85 85 uint8_t v = d[*i]; *i = *i + 1; uint8_t v = d[*i]; *i = *i + 1;
86 snprintf(out, out_size, "%s%s", prefix, v == 0 ? "NOK" : "OK");
86 snprintf(out, out_size, "%s%s", prefix, v == 0 ? "nok" : "ok");
87 87 return v; return v;
88 88 } }
89 89
 
... ... static int decode_sqlite3_ret(char *out, unsigned out_size,
645 645 return ret; return ret;
646 646 } }
647 647
648 static int decode_sqlite3_open_flags(char *out, unsigned out_size,
649 unsigned char *d, unsigned int *i)
650 {
651 unsigned int ret = decode32(d, i);
652
653 char *a = ""; if (ret & 0x00000001) a = "|READONLY";
654 char *b = ""; if (ret & 0x00000002) b = "|READWRITE";
655 char *c = ""; if (ret & 0x00000004) c = "|CREATE";
656 char *e = ""; if (ret & 0x00000008) e = "|DELETEONCLOSE";
657 char *f = ""; if (ret & 0x00000010) f = "|EXCLUSIVE";
658 char *g = ""; if (ret & 0x00000020) g = "|AUTOPROXY";
659 char *h = ""; if (ret & 0x00000040) h = "|URI";
660 char *j = ""; if (ret & 0x00000080) j = "|MEMORY";
661 char *k = ""; if (ret & 0x00000100) k = "|MAIN_DB";
662 char *l = ""; if (ret & 0x00000200) l = "|TEMP_DB";
663 char *m = ""; if (ret & 0x00000400) m = "|TRANSIENT_DB";
664 char *n = ""; if (ret & 0x00000800) n = "|MAIN_JOURNAL";
665 char *o = ""; if (ret & 0x00001000) o = "|TEMP_JOURNAL";
666 char *p = ""; if (ret & 0x00002000) p = "|SUBJOURNAL";
667 char *q = ""; if (ret & 0x00004000) q = "|SUPER_JOURNAL";
668 char *r = ""; if (ret & 0x00008000) r = "|NOMUTEX";
669 char *s = ""; if (ret & 0x00010000) s = "|FULLMUTEX";
670 char *t = ""; if (ret & 0x00020000) t = "|SHAREDCACHE";
671 char *u = ""; if (ret & 0x00040000) u = "|PRIVATECACHE";
672 char *v = ""; if (ret & 0x00080000) v = "|WAL";
673 char *w = ""; if (ret & 0x00100000) w = "|NOFOLLOW";
674
675 snprintf(out, out_size, "0x%x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
676 ret, a, b, c, e, f, g, h, j, k, l, m, n, o, p, q, r, s, t, u, v, w);
677
678 return ret;
679 }
680
648 681 static int decode_mysql_real_connect_flags(char *out, unsigned out_size, static int decode_mysql_real_connect_flags(char *out, unsigned out_size,
649 682 unsigned char *d, unsigned int *i) unsigned char *d, unsigned int *i)
650 683 { {
 
... ... static int decode_mysql_real_connect_flags(char *out, unsigned out_size,
657 690 char *interact = ""; if (ret & 1024) interact = "|INTERACTIVE"; char *interact = ""; if (ret & 1024) interact = "|INTERACTIVE";
658 691 char *ssl = ""; if (ret & 2048) ssl = "SSL"; char *ssl = ""; if (ret & 2048) ssl = "SSL";
659 692
660 snprintf(out, out_size, "%x%s%s%s%s%s%s",
693 snprintf(out, out_size, "0x%x%s%s%s%s%s%s",
661 694 ret, found_rows, compress, dont_ver, ret, found_rows, compress, dont_ver,
662 695 ignore_space, interact, ssl); ignore_space, interact, ssl);
663 696
 
... ... static int decode_dlopen_flags(char *out, size_t out_size,
677 710 char *noload = ""; if (ret & RTLD_NOLOAD) nodel = "|NOLOAD"; char *noload = ""; if (ret & RTLD_NOLOAD) nodel = "|NOLOAD";
678 711 char *deep = ""; if (ret & RTLD_DEEPBIND) deep = "|DEEPBIND"; char *deep = ""; if (ret & RTLD_DEEPBIND) deep = "|DEEPBIND";
679 712
680 snprintf(out, out_size, "%s%s%s%s%s%s%s",
681 lazy, now, global, local, nodel, noload, deep);
713 snprintf(out, out_size, "0x%x%s%s%s%s%s%s%s",
714 ret, lazy, now, global, local, nodel, noload, deep);
715
716 return ret;
717 }
718
719 static int decode_mysqli_mode(char *out, size_t out_size,
720 unsigned char *d, unsigned int *i)
721 {
722 int mode = decode32(d, i);
723
724 if (mode == 1)
725 snprintf(out, out_size, "MYSQLI_ASSOC");
726 else if (mode == 2)
727 snprintf(out, out_size, "MYSQLI_NUM");
728 else if (mode == 3)
729 snprintf(out, out_size, "MYSQLI_BOTH");
730
731 return mode;
732 }
733
734 static void decode_query_params(char *out, size_t out_size,
735 unsigned char *d, unsigned int *i)
736 {
737 size_t len, rest = out_size - 1 - 1; // -1 for \0 and -1 for '}'
738
739 uint16_t params_len = decode16(d, i);
740 if (params_len == 0) {
741 out[0] = '\0';
742 return;
743 }
744
745 if (rest >= 2) {
746 strcpy(out, " {");
747 rest -= 2;
748 }
749
750 char *add = "";
751 for (unsigned short j = 0; j < params_len; j++) {
752 char value[64];
753 uint8_t type = decode8(d, i);
754 if (type == 1) { // long
755 snprintf(value, sizeof(value),
756 "%hu:long:%ld", j + 1, decode64(d, i));
757 } else if (type == 2) { // double
758 snprintf(value, sizeof(value),
759 "%hu:double:%f", j + 1, (double) decode64(d, i));
760 } else if (type == 3) { // string
761 uint16_t len = decode16(d, i);
762 char s[len * 4 + 1];
763 bin2hex_ascii(s, d + *i, len); *i = *i + len;
764 snprintf(value, sizeof(value),
765 "%hu:str:'%s'", j + 1, s);
766 }
767
768 len = 2 + strlen(value);
769 if (len > rest)
770 break;
771
772 strcat(out, add);
773 strcat(out, value);
774 add = ", ";
775 rest -= len;
776 }
777
778 strcat(out, "}");
779 }
780
781 static int decode_h_errno(char *out, const size_t out_size, unsigned char *d, unsigned int *i)
782 {
783 int ret = decode32(d, i);
784
785 switch (ret) {
786 case HOST_NOT_FOUND: snprintf(out, out_size, "HOST_NOT_FOUND"); break;
787 case NO_DATA: snprintf(out, out_size, "NO_DATA"); break;
788 case NO_RECOVERY: snprintf(out, out_size, "NO_RECOVERY"); break;
789 case TRY_AGAIN: snprintf(out, out_size, "TRY_AGAIN"); break;
790 default: snprintf(out, out_size, "todd(%d)", ret);
791 }
682 792
683 793 return ret; return ret;
684 794 } }
685 795
796 static void decode_hostent(char *out, const size_t out_size, unsigned char *d, unsigned int *i)
797 {
798 uint8_t len = decode8(d, i);
799 char name[len * 4 + 1];
800 bin2hex_ascii(name, d + *i, len); *i = *i + len;
801
802 char aliases[512] = {0}; char *add = "";
803 for (int j = 0; ; j++) {
804 uint8_t alen = decode8(d, i);
805 if (alen == 0)
806 break;
807
808 char alias[alen * 4 + 1];
809 bin2hex_ascii(alias, d + *i, alen); *i = *i + alen;
810 strcat(aliases, add); add = ",";
811 strcat(aliases, alias);
812 }
813
814 uint8_t addrtype = decode8(d, i);
815 uint8_t h_length = decode8(d, i);
816 uint8_t count = decode8(d, i);
817 char addrs[512] = {0}; add = "";
818 for (int j = 0; j < count; j++) {
819 char addr[40];
820 const char *r = inet_ntop(addrtype, d + *i, addr, sizeof(addr));
821 if (!r)
822 bin2hex(addr, d + *i, h_length);
823 *i = *i + h_length;
824 strcat(addrs, add); add = ", ";
825 strcat(addrs, addr);
826 }
827
828 snprintf(out, out_size, " => name=[%s] aliases={%s} addrs={%s}",
829 name, aliases, addrs);
830 }
831
686 832 static void decode_func(const uint32_t parent, unsigned char *d) static void decode_func(const uint32_t parent, unsigned char *d)
687 833 { {
688 834 unsigned int i = 0; unsigned int i = 0;
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
827 973 decode_ret_pointer(rest, sizeof(rest), d, &i); decode_ret_pointer(rest, sizeof(rest), d, &i);
828 974 sprintf(line, "(%s, '%s', {%s}, 0x%x)%s", sprintf(line, "(%s, '%s', {%s}, 0x%x)%s",
829 975 dirfd, pathname, sstat, flags, rest); dirfd, pathname, sstat, flags, rest);
976 } else if ((strcmp(func, "fsync") == 0)
977 || (strcmp(func, "fdatasync") == 0)) {
978 int fd = decode32(d, &i);
979 if (type == 'r')
980 decode_ret_int(rest, sizeof(rest), d, &i);
981 sprintf(line, "(%d)%s", fd, rest);
830 982 } break; } break;
831 983
832 984 case 'g': case 'g':
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
867 1019 if (type == 'r') if (type == 'r')
868 1020 decode_ret_int(rest, sizeof(rest), d, &i); decode_ret_int(rest, sizeof(rest), d, &i);
869 1021 sprintf(line, "('%s')%s", host, rest); sprintf(line, "('%s')%s", host, rest);
1022 } else if (strcmp(func, "gethostbyname_r") == 0) {
1023 uint16_t len = decode16(d, &i);
1024 char host[len * 4 + 1];
1025 bin2hex_ascii(host, d + i, len); i += len;
1026 if (type == 'r') {
1027 int ret = decode32(d, &i);
1028 if (ret == -1)
1029 decode_h_errno(rest, sizeof(rest), d, &i);
1030 else
1031 decode_hostent(rest, sizeof(rest), d, &i);
1032 }
1033 sprintf(line, "('%s')%s", host, rest);
870 1034 } else if (strcmp(func, "getrandom") == 0) { } else if (strcmp(func, "getrandom") == 0) {
871 1035 size_t buflen = decode64(d, &i); size_t buflen = decode64(d, &i);
872 1036 unsigned int flags = decode32(d, &i); unsigned int flags = decode32(d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
910 1074 } break; } break;
911 1075
912 1076 case 'm': case 'm':
913 if (strcmp(func, "mysqli_close") == 0) {
1077 if (strcmp(func, "mysqli_autocommit") == 0) {
1078 uint64_t link = decode64(d, &i);
1079 uint8_t value = decode8(d, &i);
1080 if (type == 'r')
1081 decode_bool(" = ", rest, sizeof(rest), d, &i);
1082 sprintf(line, "(link=0x%lx, %s)%s",
1083 link, value == 0 ? "false" : "true", rest);
1084 } else if (strcmp(func, "mysqli_close") == 0) {
914 1085 uint64_t link = decode64(d, &i); uint64_t link = decode64(d, &i);
915 1086 if (type == 'r') if (type == 'r')
916 1087 decode_bool(" = ", rest, sizeof(rest), d, &i); decode_bool(" = ", rest, sizeof(rest), d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
923 1094 if (type == 'r') if (type == 'r')
924 1095 decode_bool(" = ", rest, sizeof(rest), d, &i); decode_bool(" = ", rest, sizeof(rest), d, &i);
925 1096 sprintf(line, "('%s')%s", cs, rest); sprintf(line, "('%s')%s", cs, rest);
1097 } else if (strcmp(func, "mysqli_fetch_all") == 0) {
1098 uint64_t res = decode64(d, &i);
1099 char mode[64];
1100 decode_mysqli_mode(mode, sizeof(mode), d ,&i);
1101 if (type == 'r')
1102 snprintf(rest, sizeof(rest), " [%lu row(s)]", decode64(d, &i));
1103 sprintf(line, "(0x%lx, %s)%s", res, mode, rest);
1104 } else if (strcmp(func, "mysqli_fetch_array") == 0) {
1105 uint64_t res = decode64(d, &i);
1106 char mode[64];
1107 decode_mysqli_mode(mode, sizeof(mode), d ,&i);
1108 if (type == 'r') {
1109 uint8_t ret = decode8(d, &i);
1110 if (ret == 0)
1111 snprintf(rest, sizeof(rest), " = no row");
1112 else if (ret == 1)
1113 snprintf(rest, sizeof(rest), " = nok");
1114 else if (ret == 2)
1115 snprintf(rest, sizeof(rest), " = ok");
1116 }
1117 sprintf(line, "(0x%lx, %s)%s", res, mode, rest);
1118 } else if (strcmp(func, "mysqli_free_result") == 0) {
1119 uint64_t res = decode64(d, &i);
1120 sprintf(line, "(0x%lx)", res);
1121 } else if (strcmp(func, "mysqli_prepare") == 0) {
1122 uint64_t link = decode64(d, &i);
1123 uint16_t q_len = decode16(d, &i);
1124 char q[q_len * 4 + 1];
1125 bin2hex_ascii(q, d + i, q_len); i += q_len;
1126 if (type == 'r') {
1127 uint64_t stmt = decode64(d, &i);
1128 snprintf(rest, sizeof(rest), " = 0x%lx", stmt);
1129 }
1130 sprintf(line, "(link=0x%lx, '%s')%s", link, q, rest);
926 1131 } else if (strcmp(func, "mysqli_query") == 0) { } else if (strcmp(func, "mysqli_query") == 0) {
927 1132 uint64_t link = decode64(d, &i); uint64_t link = decode64(d, &i);
928 1133 uint16_t q_len = decode16(d, &i); uint16_t q_len = decode16(d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
948 1153 if (type == 'r') if (type == 'r')
949 1154 decode_bool(" = ", rest, sizeof(rest), d, &i); decode_bool(" = ", rest, sizeof(rest), d, &i);
950 1155 sprintf(line, "(link=0x%lx, '%s', flags='%s')%s", link, cs, flags, rest); sprintf(line, "(link=0x%lx, '%s', flags='%s')%s", link, cs, flags, rest);
1156 } else if (strcmp(func, "mysqli_stmt_execute") == 0) {
1157 char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1158 uint64_t stmt = decode64(d, &i);
1159 if (type == 'c') {
1160 decode_query_params(rest, sizeof(rest), d, &i);
1161 sprintf(line, "(stmt=0x%lx%s%s)",
1162 stmt, rest[0] ? ", " : "", rest);
1163 } else if (type == 'r') {
1164 uint8_t ret = decode8(d, &i);
1165 if (ret == 1)
1166 snprintf(rest, sizeof(rest), " = ok");
1167 else
1168 snprintf(rest, sizeof(rest), " = nok");
1169 sprintf(line, "(stmt=0x%lx)%s", stmt, rest);
1170 }
1171 } else if (strcmp(func, "mysqli_stmt_prepare") == 0) {
1172 uint64_t stmt = decode64(d, &i);
1173 uint16_t q_len = decode16(d, &i);
1174 char q[q_len * 4 + 1];
1175 bin2hex_ascii(q, d + i, q_len); i += q_len;
1176 if (type == 'r')
1177 decode_bool(" = ", rest, sizeof(rest), d, &i);
1178 sprintf(line, "(stmt=0x%lx, '%s')%s", stmt, q, rest);
951 1179 } break; } break;
952 1180
953 1181 case 'n': case 'n':
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1010 1238 decode_ret_int(rest, sizeof(rest), d, &i); decode_ret_int(rest, sizeof(rest), d, &i);
1011 1239 sprintf(line, "([%s], %u, %d)%s", sprintf(line, "([%s], %u, %d)%s",
1012 1240 list, nf, timeout, rest); list, nf, timeout, rest);
1241 } else if ((strcmp(func, "pread") == 0)
1242 || (strcmp(func, "pread64") == 0)) {
1243 int fd = decode32(d, &i);
1244 size_t count = decode64(d, &i);
1245 off_t offset = decode64(d, &i);
1246 if (type == 'c') {
1247 sprintf(line, "(%d, buf, %zu, off=%zu)", fd, count, offset);
1248 } else {
1249 ssize_t ret = decode_ret_int64(rest, sizeof(rest), d, &i);
1250 if (ret > 0) {
1251 unsigned short max = decode16(d, &i);
1252 char data[max * 4 + 1];
1253 bin2hex_ascii(data, d + i, max); i += max;
1254 sprintf(line, "(%d, '%s'%s, %zu, off=%zu)%s",
1255 fd, data,
1256 max < ret ? "..." : "", count, offset, rest);
1257 } else {
1258 sprintf(line, "(%d, buf, %zu, off=%zu)%s",
1259 fd, count, offset, rest);
1260 }
1261 }
1262 } else if ((strcmp(func, "pwrite") == 0)
1263 || (strcmp(func, "pwrite64") == 0)) {
1264 int fd = decode32(d, &i);
1265 size_t count = decode64(d, &i);
1266 off_t offset = decode64(d, &i);
1267 if (type == 'c') {
1268 unsigned short max = decode16(d, &i);
1269 char data[max * 4 + 1];
1270 bin2hex_ascii(data, d + i, max); i += max;
1271 sprintf(line, "(%d, '%s'%s, %zu, off=%zu)",
1272 fd, data,
1273 max < count ? "..." : "", count, offset);
1274 } else {
1275 decode_ret_int64(rest, sizeof(rest), d, &i);
1276 sprintf(line, "(%d, buf, %zu, off=%zu)%s",
1277 fd, count, offset, rest);
1278 }
1013 1279 } else if (strcmp(func, "pg_close") == 0) { } else if (strcmp(func, "pg_close") == 0) {
1014 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1015 1280 uint64_t h = decode64(d, &i); uint64_t h = decode64(d, &i);
1016 sprintf(line, "(0x%lx)", h);
1281 if (h == 0)
1282 sprintf(line, "()");
1283 else
1284 sprintf(line, "(0x%lx)", h);
1017 1285 } else if ((strcmp(func, "pg_connect") == 0) } else if ((strcmp(func, "pg_connect") == 0)
1018 1286 || (strcmp(func, "pg_pconnect") == 0)) { || (strcmp(func, "pg_pconnect") == 0)) {
1019 1287 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump); //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1038 1306 uint16_t q_len = decode16(d, &i); uint16_t q_len = decode16(d, &i);
1039 1307 char q[q_len * 4 + 1]; char q[q_len * 4 + 1];
1040 1308 bin2hex_ascii(q, d + i, q_len); i += q_len; bin2hex_ascii(q, d + i, q_len); i += q_len;
1041 while (type == 'c') {
1042 uint16_t params_len = decode16(d, &i);
1043 uint16_t max = decode16(d, &i);
1044 if (max == 0)
1045 break;
1046
1047 // TODO: 'rest' may not be big enough!
1048 strcpy(rest, " {");
1049 char *add = "";
1050 for (unsigned short j = 0; j < max; j++) {
1051 char value[64];
1052 uint8_t type = decode8(d, &i);
1053 if (type == 1) { // long
1054 snprintf(value, sizeof(value),
1055 "%hu:long:%ld", j + 1, decode64(d, &i));
1056 } else if (type == 2) { // double
1057 snprintf(value, sizeof(value),
1058 "%hu:double:%f", j + 1, (double) decode64(d, &i));
1059 } else if (type == 3) { // string
1060 uint16_t len = decode16(d, &i);
1061 char s[len * 4 + 1];
1062 bin2hex_ascii(s, d + i, len); i += len;
1063 snprintf(value, sizeof(value),
1064 "%hu:str:'%s'", j + 1, s);
1065 }
1066
1067 strcat(rest, add);
1068 strcat(rest, value);
1069 add = ", ";
1070 }
1071 if (max < params_len)
1072 strcat(rest, "...");
1073 strcat(rest, "}");
1074 break;
1075 }
1076 if (type == 'r') {
1309 if (type == 'c') {
1310 decode_query_params(rest, sizeof(rest), d, &i);
1311 } else if (type == 'r') {
1077 1312 uint64_t res = decode64(d, &i); uint64_t res = decode64(d, &i);
1078 1313 uint64_t rows = decode64(d, &i); uint64_t rows = decode64(d, &i);
1079 1314 uint64_t aff = decode64(d, &i); uint64_t aff = decode64(d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1100 1335 res, rows, aff); res, rows, aff);
1101 1336 } }
1102 1337 sprintf(line, "(h=0x%lx)%s", dbh, rest); sprintf(line, "(h=0x%lx)%s", dbh, rest);
1338 } else if (strcmp(func, "pthread_attr_setstacksize") == 0) {
1339 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1340 uint64_t attr = decode64(d, &i);
1341 size_t stack_size = decode64(d, &i);
1342 decode_ret_int(rest, sizeof(rest), d, &i);
1343 sprintf(line, "(attr=0x%lx, %zu)%s",
1344 attr, stack_size, rest);
1345 } else if (strcmp(func, "pthread_create") == 0) {
1346 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1347 uint64_t thread = decode64(d, &i);
1348 uint64_t attr = decode64(d, &i);
1349 uint64_t arg = decode64(d, &i);
1350 decode_ret_int(rest, sizeof(rest), d, &i);
1351 sprintf(line, "(thread=%lu, attr=0x%lx, arg=0x%lx)%s",
1352 thread, attr, arg, rest);
1353 } else if (strcmp(func, "pthread_setname_np") == 0) {
1354 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1355 uint64_t thread = decode64(d, &i);
1356 uint16_t len = decode16(d, &i);
1357 char name[len * 4 + 1];
1358 bin2hex_ascii(name, d + i, len); i += len;
1359 decode_ret_int(rest, sizeof(rest), d, &i);
1360 sprintf(line, "(thread=%lu, '%s')%s",
1361 thread, name, rest);
1103 1362 } break; } break;
1104 1363
1105 1364 case 'r': case 'r':
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1212 1471 sprintf(line, "(%s, %s, %d)%s", sprintf(line, "(%s, %s, %d)%s",
1213 1472 decode_socket_domain(xdomain), decode_socket_domain(xdomain),
1214 1473 decode_socket_type(xtype), xprotocol, rest); decode_socket_type(xtype), xprotocol, rest);
1474 } else if (strcmp(func, "sqlite3_bind_double") == 0) {
1475 uint64_t stmt = decode64(d, &i);
1476 int index = decode32(d, &i);
1477 double value = decode64(d, &i);
1478 decode_sqlite3_ret(rest, sizeof(rest), d, &i);
1479 sprintf(line, "(0x%lx, index=%d, value=%f) = %s",
1480 stmt, index, value, rest);
1481 } else if (strcmp(func, "sqlite3_bind_int") == 0) {
1482 uint64_t stmt = decode64(d, &i);
1483 int index = decode32(d, &i);
1484 int value = decode32(d, &i);
1485 decode_sqlite3_ret(rest, sizeof(rest), d, &i);
1486 sprintf(line, "(0x%lx, index=%d, value=%d) = %s",
1487 stmt, index, value, rest);
1488 } else if (strcmp(func, "sqlite3_bind_int64") == 0) {
1489 uint64_t stmt = decode64(d, &i);
1490 int index = decode32(d, &i);
1491 int64_t value = decode64(d, &i);
1492 decode_sqlite3_ret(rest, sizeof(rest), d, &i);
1493 sprintf(line, "(0x%lx, index=%d, value=%ld) = %s",
1494 stmt, index, value, rest);
1495 } else if (strcmp(func, "sqlite3_bind_text") == 0) {
1496 uint64_t stmt = decode64(d, &i);
1497 int index = decode32(d, &i);
1498 int16_t len = decode16(d, &i);
1499 char value[len * 4 + 1];
1500 bin2hex_ascii(value, d + i, len); i += len;
1501 decode_sqlite3_ret(rest, sizeof(rest), d, &i);
1502 sprintf(line, "(stmt=0x%lx, index=%d, '%s') = %s",
1503 stmt, index, value, rest);
1504 } else if (strcmp(func, "sqlite3_finalize") == 0) {
1505 uint64_t stmt = decode64(d, &i);
1506 decode_sqlite3_ret(rest, sizeof(rest), d, &i);
1507 sprintf(line, "(0x%lx)%s%s", stmt, rest[0] ? " = " : "", rest);
1215 1508 } else if (strcmp(func, "sqlite3_open_v2") == 0) { } else if (strcmp(func, "sqlite3_open_v2") == 0) {
1216 1509 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump); //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1217 1510 uint16_t filename_len = decode16(d, &i); uint16_t filename_len = decode16(d, &i);
1218 1511 char filename[filename_len * 4 + 1]; char filename[filename_len * 4 + 1];
1219 1512 bin2hex_ascii(filename, d + i, filename_len); i += filename_len; bin2hex_ascii(filename, d + i, filename_len); i += filename_len;
1220 int flags = decode32(d, &i);
1513 char flags[128];
1514 decode_sqlite3_open_flags(flags, sizeof(flags), d, &i);
1221 1515 uint16_t vfs_len = decode16(d, &i); uint16_t vfs_len = decode16(d, &i);
1222 1516 char vfs[vfs_len * 4 + 1]; char vfs[vfs_len * 4 + 1];
1223 1517 bin2hex_ascii(vfs, d + i, vfs_len); i += vfs_len; bin2hex_ascii(vfs, d + i, vfs_len); i += vfs_len;
1224 1518
1225 1519 if (type == 'c') { if (type == 'c') {
1226 sprintf(line, "('%s', 0x%x, '%s')",
1520 sprintf(line, "('%s', %s, '%s')",
1227 1521 filename, flags, vfs); filename, flags, vfs);
1228 1522 } else { } else {
1229 1523 char err[64]; char err[64];
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1231 1525 uint64_t pdb = 0; uint64_t pdb = 0;
1232 1526 if (ret == 0) if (ret == 0)
1233 1527 pdb = decode64(d, &i); pdb = decode64(d, &i);
1234 sprintf(line, "('%s', 0x%lx, 0x%x, '%s') = %s",
1528 sprintf(line, "('%s', 0x%lx, %s, '%s') = %s",
1235 1529 filename, pdb, flags, vfs, err); filename, pdb, flags, vfs, err);
1236 1530 } }
1237 1531 } else if (strcmp(func, "sqlite3_prepare_v2") == 0) { } else if (strcmp(func, "sqlite3_prepare_v2") == 0) {
Date/time (UTC) Type Misc Labels
2022-11-21 14:22 build fedora-37-x86_64 worker/r1 builder/color=fff worker_elap/308s wait_time/289810s date/2022-11-18 time/05:41
2022-11-21 14:35 build fedora-rawhide-x86_64 worker/r1 builder/color=fff worker_elap/567s wait_time/290628s date/2022-11-18 time/05:41
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/catalinux/ninedogs

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/catalinux/ninedogs

Clone this repository using git:
git clone git://git.rocketgit.com/user/catalinux/ninedogs

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main