List of commits:
Subject Hash Author Date (UTC)
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 d9d83cafbd372d1055fa2e51cdf3deb2396f5d08 - mysql, sqlite3, depth
Author: Catalin(ux) M. BOIE
Author date (UTC): 2022-11-07 05:58
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2022-11-07 05:58
Parent(s): 3867b17137b5397c3eeabdcbbc232417ad212a27
Signer:
Signing key:
Signing status: N
Tree: fb04cb819dda51e4e5ecd32ddbd3615cd67fb5dc
File Lines added Lines deleted
.gitignore 3 0
agent/.gitignore 0 1
agent/Makefile 4 0
agent/TODO 2 0
agent/ctools.c 14 14
agent/ninedogs.TODO 9 0
agent/ninedogs.c 517 162
agent/ninedogs.h 1 0
agent/php.c 504 150
agent/process_core.c 4 3
agent/process_db.c 78 40
agent/process_db.h 39 14
agent/process_misc.c 1 1
agent/python.c 253 226
agent/python.h 2 0
agent/text2process.c 2 1
common/ids.h 5 2
common/shared.h 2 1
docs/pre1.txt 7 0
test/container/Dockerfile 13 0
test/container/build.sh 10 0
test/container/exec-dev.sh 7 0
test/container/exec.sh 3 0
test/php-container/1 9 0
test/php-container/1.php 35 0
test/php-container/Dockerfile 14 0
test/php-container/build.sh 10 0
test/php-container/exec-dev-1.sh 11 0
test/php-container/exec-dev.sh 11 0
test/php-container/exec.sh 3 0
test/php-mysql/1.php 93 0
test/php-mysql/1.run 3 2
test/php-pg/1.run 1 1
test/php-pg/1.run.gdb 1 1
test/python/redis1.py 6 0
test/python/redis1.run 10 5
test/python/sqlite1.py 34 0
test/python/sqlite1.run 7 5
test/rg/1.run 1 1
test/segv1/1.run 1 1
trace/TODO 7 0
trace/nd-trace.c 411 51
File .gitignore changed (mode: 100644) (index debb986..c3ccba7)
... ... obj/
16 16 *.old *.old
17 17 *.ok *.ok
18 18 *.classes *.classes
19 *.nd
20 *.db
21 *.asm
File agent/.gitignore changed (mode: 100644) (index 56b2dfa..d83fc46)
1 1 sock1 sock1
2 2 sock2 sock2
3 3 *.dump *.dump
4 *.asm
5 4 *.gz *.gz
File agent/Makefile changed (mode: 100644) (index 55be1a2..c980a15)
... ... CFLAGS += -I../common
9 9
10 10 OBJS := decode.o ctools.o php.o process.o process_core.o process_misc.o \ OBJS := decode.o ctools.o php.o process.o process_core.o process_misc.o \
11 11 process_db.o process_ssl.o openssl.o gnutls.o text2process.o \ process_db.o process_ssl.o openssl.o gnutls.o text2process.o \
12 python.o \
12 13 ../common/tools.o ../common/tools.o
13 14
14 15 decode.o: decode.c decode.h process_db.h $(COMMON_H) decode.o: decode.c decode.h process_db.h $(COMMON_H)
 
... ... ctools.o: ctools.c $(COMMON_H) ../common/tools.h
20 21 php.o: php.c php.h process_db.h $(COMMON_H) php.o: php.c php.h process_db.h $(COMMON_H)
21 22 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
22 23
24 python.o: python.c python.h process_db.h $(COMMON_H)
25 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
26
23 27 openssl.o: openssl.c openssl.h process_ssl.h $(COMMON_H) openssl.o: openssl.c openssl.h process_ssl.h $(COMMON_H)
24 28 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
25 29
File agent/TODO changed (mode: 100644) (index 985af8c..d4cfcb4)
1 1 == Urgent == == Urgent ==
2 [ ] Move my_trace into a separate file.
2 3 [ ] My functions can overwrite errno. Pay attention to this! [ ] My functions can overwrite errno. Pay attention to this!
3 4 [ ] [ ]
4 5
 
... ... send q2 str
14 15 close conn close conn
15 16
16 17 == Random == == Random ==
18 [ ] Add an identification for the pids attached, to store them in the log.
17 19 [ ] Server message decoding is not working right I suspect. [ ] Server message decoding is not working right I suspect.
18 20 [ ] Investigate ltrace sources! [ ] Investigate ltrace sources!
19 21 [ ] Use sbrk to know the heap size. [ ] Use sbrk to know the heap size.
File agent/ctools.c changed (mode: 100644) (index a61aa63..c5e5329)
... ... void server_init(void)
376 376 if (inited) if (inited)
377 377 return; return;
378 378
379 xlog(10, "%s...\n", __func__);
379 xlog(100, "%s...\n", __func__);
380 380
381 381 do { do {
382 382 do { do {
 
... ... void server_init(void)
409 409 break; break;
410 410 } }
411 411 } while (0); } while (0);
412 xlog(10, "id is [%s]\n", id);
412 xlog(101, "id is [%s]\n", id);
413 413
414 414 server = getenv("NINEDOGS_SERVER_HOSTNAME"); server = getenv("NINEDOGS_SERVER_HOSTNAME");
415 415 port = getenv("NINEDOGS_SERVER_PORT"); port = getenv("NINEDOGS_SERVER_PORT");
 
... ... void server_init(void)
418 418 url = getenv("NINEDOGS_SERVER_URL"); url = getenv("NINEDOGS_SERVER_URL");
419 419 if (!url || (*url == '\0')) if (!url || (*url == '\0'))
420 420 url = "/ingest"; url = "/ingest";
421 xlog(20, "server=[%s] port=[%s] url=[%s]\n",
421 xlog(101, "server=[%s] port=[%s] url=[%s]\n",
422 422 server ? server : "n/a", port, url); server ? server : "n/a", port, url);
423 423
424 424 if (!server || (*server == '\0')) { if (!server || (*server == '\0')) {
 
... ... void server_init(void)
435 435 } }
436 436
437 437 /* X509 stuff */ /* X509 stuff */
438 xlog(20, "Allocating credentials...\n");
438 xlog(101, "Allocating credentials...\n");
439 439 r = gnutls_certificate_allocate_credentials(&xcred); r = gnutls_certificate_allocate_credentials(&xcred);
440 440 if (r != GNUTLS_E_SUCCESS) { if (r != GNUTLS_E_SUCCESS) {
441 441 xlog(10, "gnutls error: cannot allocate credentials: %s\n", gnutls_strerror(r)); xlog(10, "gnutls error: cannot allocate credentials: %s\n", gnutls_strerror(r));
 
... ... void server_init(void)
444 444 } }
445 445
446 446 /* sets the system trusted CAs for Internet PKI */ /* sets the system trusted CAs for Internet PKI */
447 xlog(20, "Setting system trust...\n");
447 xlog(101, "Setting system trust...\n");
448 448 r = gnutls_certificate_set_x509_system_trust(xcred); r = gnutls_certificate_set_x509_system_trust(xcred);
449 449 if (r < 0) { if (r < 0) {
450 450 xlog(10, "gnutls error: cannot set system trust: %s!\n", gnutls_strerror(r)); xlog(10, "gnutls error: cannot set system trust: %s!\n", gnutls_strerror(r));
 
... ... void server_init(void)
454 454 } while (0); } while (0);
455 455
456 456 inited = 1; inited = 1;
457 xlog(10, "%s done\n", __func__);
457 xlog(100, "%s done\n", __func__);
458 458 } }
459 459
460 460 void server_enqueue(void *buf, const unsigned int len) void server_enqueue(void *buf, const unsigned int len)
 
... ... void server_pat(const char sync)
796 796 if (server_is_disabled) if (server_is_disabled)
797 797 return; return;
798 798
799 xlog(10, "%s sync=%hhd...\n", __func__, sync);
799 xlog(100, "%s sync=%hhd...\n", __func__, sync);
800 800
801 801 server_init(); server_init();
802 802 while (1) { while (1) {
803 803 server_connect(); server_connect();
804 804 if ((sync == 1) && (conn_state != CONN_STATE_OK)) { if ((sync == 1) && (conn_state != CONN_STATE_OK)) {
805 xlog(50, "%s: state=%s\n", __func__, conn_state_name(conn_state));
805 xlog(101, "%s: state=%s\n", __func__, conn_state_name(conn_state));
806 806 poll_wait(server_fd, POLLIN, 1000); poll_wait(server_fd, POLLIN, 1000);
807 807 continue; continue;
808 808 } }
 
... ... void server_pat(const char sync)
836 836 break; break;
837 837 } }
838 838
839 dump(10, "tls sending", server_head->data + server_head->data_off,
839 dump(101, "tls sending", server_head->data + server_head->data_off,
840 840 server_head->data_len - server_head->data_off); server_head->data_len - server_head->data_off);
841 841 do { do {
842 842 r = gnutls_record_send(server_session, r = gnutls_record_send(server_session,
 
... ... void server_pat(const char sync)
844 844 server_head->data_len - server_head->data_off); server_head->data_len - server_head->data_off);
845 845 } while ((sync == 1) && (r == GNUTLS_E_AGAIN)); } while ((sync == 1) && (r == GNUTLS_E_AGAIN));
846 846 if (r == 0) { if (r == 0) {
847 xlog(1, " server closed connection\n");
847 xlog(100, " server closed connection\n");
848 848 break; break;
849 849 } }
850 850 if (r < 0) { if (r < 0) {
851 851 if (r == GNUTLS_E_AGAIN) if (r == GNUTLS_E_AGAIN)
852 852 return; return;
853 853
854 xlog(10, " gnutls_record_send returned: %s\n", gnutls_strerror(r));
854 xlog(101, " gnutls_record_send returned: %s\n", gnutls_strerror(r));
855 855 conn_state = CONN_STATE_RETRY; conn_state = CONN_STATE_RETRY;
856 856 break; break;
857 857 } }
 
... ... void server_pat(const char sync)
870 870 } }
871 871
872 872 // TODO: keep alive the connection here // TODO: keep alive the connection here
873 xlog(10, " %s finished WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW\n", __func__);
873 xlog(101, " %s finished WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW\n", __func__);
874 874 } }
875 875
876 876 void server_stop(void) void server_stop(void)
877 877 { {
878 xlog(10, "%s...\n", __func__);
878 xlog(100, "%s...\n", __func__);
879 879
880 880 //if (server_session) { //if (server_session) {
881 881 // xlog(10, "%s: Sending bye...\n", __func__); // xlog(10, "%s: Sending bye...\n", __func__);
 
... ... void server_stop(void)
883 883 // xlog(10, "%s: bye returned: %s\n", __func__, gnutls_strerror(r)); // xlog(10, "%s: bye returned: %s\n", __func__, gnutls_strerror(r));
884 884 //} //}
885 885
886 xlog(10, "%s done\n", __func__);
886 xlog(100, "%s done\n", __func__);
887 887 } }
888 888
889 889
File agent/ninedogs.TODO added (mode: 100644) (index 0000000..5647d78)
1
2 Move from:
3 int ret = va_arg(va, int);
4 my_trace_put32(buf, &i, ret);
5 if (ret == -1)
6 my_trace_put32(buf, &i, save_errno);
7
8 to:
9 my_trace_put_err_int(buf, &i, va_arg(va, int), save_errno)
File agent/ninedogs.c changed (mode: 100644) (index 0619a40..b3a0dd7)
45 45 #include "ninedogs.h" #include "ninedogs.h"
46 46 #include "ids.h" #include "ids.h"
47 47 #include "php.h" #include "php.h"
48 #include "python.h"
48 49 #include "tools.h" #include "tools.h"
49 50 #include "ctools.h" #include "ctools.h"
50 51 #include "process_core.h" #include "process_core.h"
52 #include "process_db.h"
51 53 #include "text2process.h" #include "text2process.h"
52 54 #include "shared.h" #include "shared.h"
53 55
 
... ... static unsigned long my_malloc_pos;
89 91 static struct shared *shared; static struct shared *shared;
90 92 static char shared_inited; static char shared_inited;
91 93 static char trace_enabled = 1; static char trace_enabled = 1;
94 static __thread unsigned short trace_depth;
92 95
93 96 static char ninedogs_inited; static char ninedogs_inited;
94 97 static void *(*old_realloc)(void *ptr, size_t size); static void *(*old_realloc)(void *ptr, size_t size);
 
... ... static ssize_t (*old_sendto)(int sockfd, const void *buf, size_t len, int flag
104 107 static ssize_t (*old_sendmsg)(int sockfd, const struct msghdr *msg, int flags); static ssize_t (*old_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
105 108 static ssize_t (*old_recv)(int sockfd, void *buf, size_t len, int flags); static ssize_t (*old_recv)(int sockfd, void *buf, size_t len, int flags);
106 109 static ssize_t (*old_recvmsg)(int sockfd, struct msghdr *msg, int flags); static ssize_t (*old_recvmsg)(int sockfd, struct msghdr *msg, int flags);
110 static ssize_t (*old_recvfrom)(int sockfd, void *restrict buf, size_t len, int flags,
111 struct sockaddr *restrict src_addr, socklen_t *restrict addrlen);
107 112 static int (*old_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen); static int (*old_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
108 113 static int (*old_accept4)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags); static int (*old_accept4)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
109 114 static int (*old_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen); static int (*old_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
 
... ... static int (*old_fstatat)(int dirfd, const char *restrict pathname,
139 144 struct stat *restrict statbuf, int flags); struct stat *restrict statbuf, int flags);
140 145 static int (*old_fstatat64)(int dirfd, const char *restrict pathname, static int (*old_fstatat64)(int dirfd, const char *restrict pathname,
141 146 struct stat64 *restrict statbuf, int flags); struct stat64 *restrict statbuf, int flags);
147 static pid_t (*old_fork)(void);
142 148
143 149 /* fd helpers */ /* fd helpers */
144 150 static struct fd_node *fd_search(const int fd) static struct fd_node *fd_search(const int fd)
 
... ... static void my_trace_put64(unsigned char *buf, unsigned int *i, const uint64_t v
218 224 memcpy(buf + *i, &u, 8); *i = *i + 8; memcpy(buf + *i, &u, 8); *i = *i + 8;
219 225 } }
220 226
227 static void my_trace_put_double(unsigned char *buf, unsigned int *i, const double v)
228 {
229 uint64_t u = htobe64(v);
230 memcpy(buf + *i, &u, 8); *i = *i + 8;
231 }
232
233 static void my_trace_put_bool(unsigned char *buf, unsigned int *i, const char v)
234 {
235 buf[*i] = v; *i = *i + 1;
236 }
237
221 238 static void my_trace_put(unsigned char *buf, unsigned int *i, static void my_trace_put(unsigned char *buf, unsigned int *i,
222 239 const void *in, const size_t in_len) const void *in, const size_t in_len)
223 240 { {
 
... ... static void my_trace_put_stat(unsigned char *buf, unsigned int *i, struct stat *
256 273 my_trace_put32(buf, i, s->st_ctim.tv_nsec); my_trace_put32(buf, i, s->st_ctim.tv_nsec);
257 274 } }
258 275
276 static void my_trace_put_string_array(unsigned char *buf, unsigned int *i, char *list[])
277 {
278 unsigned int j = 0;
279
280 while (1) {
281 if (!list[j]) {
282 my_trace_put32(buf, i, 0);
283 break;
284 }
285
286 unsigned short len = strlen(list[j]);
287 my_trace_put16(buf, i, len);
288 my_trace_put(buf, i, list[j], len);
289 j++;
290 }
291 }
292
259 293 /* /*
260 294 * Returns how many byte were stored in * Returns how many byte were stored in
261 295 */ */
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
263 297 const char *func, const char type, int save_errno, va_list va) const char *func, const char type, int save_errno, va_list va)
264 298 { {
265 299 unsigned int i, ic; unsigned int i, ic;
266 uint64_t u64;
267 300
268 301 i = 2; // first two bytes are for length i = 2; // first two bytes are for length
269 302 my_trace_put8(buf, &i, SHARED_FUNC); my_trace_put8(buf, &i, SHARED_FUNC);
270 303
271 304 struct timeval tv; struct timeval tv;
272 305 gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
273 u64 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
274 my_trace_put64(buf, &i, u64);
306 my_trace_put64(buf, &i, tv.tv_sec * 1000 + tv.tv_usec / 1000);
307 my_trace_put16(buf, &i, trace_depth);
275 308 unsigned short flen = strlen(func); unsigned short flen = strlen(func);
276 309 my_trace_put16(buf, &i, flen); my_trace_put16(buf, &i, flen);
277 310 my_trace_put(buf, &i, func, flen); my_trace_put(buf, &i, func, flen);
278 311 my_trace_put8(buf, &i, type); my_trace_put8(buf, &i, type);
279 my_trace_put32(buf, &i, htobe32(getpid()));
280 my_trace_put32(buf, &i, htobe32(gettid()));
312 my_trace_put32(buf, &i, getpid());
313 my_trace_put32(buf, &i, gettid());
281 314
282 315 ic = i; ic = i;
283 316 switch (func[0]) { switch (func[0]) {
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
388 421 } else if (strcmp(func, "dlclose") == 0) { } else if (strcmp(func, "dlclose") == 0) {
389 422 uint64_t h = (uint64_t) va_arg(va, void *); uint64_t h = (uint64_t) va_arg(va, void *);
390 423 my_trace_put64(buf, &i, h); my_trace_put64(buf, &i, h);
424 int ret = va_arg(va, int);
425 my_trace_put32(buf, &i, ret);
426 if (ret == -1)
427 my_trace_put32(buf, &i, save_errno);
428 } break;
429
430 case 'e':
431 if (strcmp(func, "execve") == 0) {
432 char *pathname = va_arg(va, char *);
433 unsigned short len = strlen(pathname);
434 my_trace_put16(buf, &i, len);
435 my_trace_put(buf, &i, pathname, len);
436 my_trace_put_string_array(buf, &i, va_arg(va, char **)); // argv
437 my_trace_put_string_array(buf, &i, va_arg(va, char **)); // envp
391 438 if (type == 'r') { if (type == 'r') {
392 439 int ret = va_arg(va, int); int ret = va_arg(va, int);
393 440 my_trace_put32(buf, &i, ret); my_trace_put32(buf, &i, ret);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
397 444 } break; } break;
398 445
399 446 case 'f': case 'f':
400 if ((strcmp(func, "fstatat") == 0)
447 if (strcmp(func, "fork") == 0) {
448 int ret = va_arg(va, int);
449 my_trace_put32(buf, &i, ret);
450 if (ret == -1)
451 my_trace_put32(buf, &i, save_errno);
452 } else if ((strcmp(func, "fstatat") == 0)
401 453 || (strcmp(func, "fstatat64") == 0)) { || (strcmp(func, "fstatat64") == 0)) {
402 454 my_trace_put16(buf, &i, va_arg(va, int)); // dirfd my_trace_put16(buf, &i, va_arg(va, int)); // dirfd
403 455 char *pathname = va_arg(va, char *); char *pathname = va_arg(va, char *);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
417 469
418 470 case 'g': case 'g':
419 471 if (strcmp(func, "getaddrinfo") == 0) { if (strcmp(func, "getaddrinfo") == 0) {
420 uint16_t len;
421
422 472 char *node = va_arg(va, char *); char *node = va_arg(va, char *);
423 len = node ? strlen(node) : 0xFFFF;
473 uint16_t len = node ? strlen(node) : 0xFFFF;
424 474 my_trace_put16(buf, &i, len); my_trace_put16(buf, &i, len);
425 475 if (node) if (node)
426 476 my_trace_put(buf, &i, node, len); my_trace_put(buf, &i, node, len);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
467 517 my_trace_put32(buf, &i, save_errno); my_trace_put32(buf, &i, save_errno);
468 518 } }
469 519 } }
520 } else if (strcmp(func, "getsockopt") == 0) {
521 my_trace_put32(buf, &i, va_arg(va, int)); // sock
522 my_trace_put32(buf, &i, va_arg(va, int)); // level
523 my_trace_put32(buf, &i, va_arg(va, int)); // optname
524 void *optval = va_arg(va, void *);
525 socklen_t optlen = va_arg(va, socklen_t);
526 my_trace_put32(buf, &i, optlen);
527 my_trace_put(buf, &i, optval, optlen);
528 int ret = va_arg(va, int);
529 my_trace_put32(buf, &i, ret);
530 if (ret == -1)
531 my_trace_put32(buf, &i, save_errno);
470 532 } break; } break;
471 533
472 534 case 'l': case 'l':
473 535 if (strcmp(func, "listen") == 0) { if (strcmp(func, "listen") == 0) {
474 536 my_trace_put32(buf, &i, va_arg(va, int)); // sock my_trace_put32(buf, &i, va_arg(va, int)); // sock
475 537 my_trace_put32(buf, &i, va_arg(va, int)); // backlog my_trace_put32(buf, &i, va_arg(va, int)); // backlog
476 if (type == 'r') {
477 int ret = va_arg(va, int);
478 my_trace_put32(buf, &i, ret);
479 if (ret == -1)
480 my_trace_put32(buf, &i, save_errno);
481 }
538 int ret = va_arg(va, int);
539 my_trace_put32(buf, &i, ret);
540 if (ret == -1)
541 my_trace_put32(buf, &i, save_errno);
542 } break;
543
544 case 'm':
545 if (strcmp(func, "mysqli_close") == 0) {
546 struct conn *c = va_arg(va, struct conn *);
547 my_trace_put64(buf, &i, (uint64_t) c->dbh);
548 if (type == 'r')
549 my_trace_put_bool(buf, &i, c->ret);
550 } else if (strcmp(func, "mysqli_connect") == 0) {
551 struct conn *c = va_arg(va, struct conn *);
552 my_trace_put32(buf, &i, c->conn_str_len);
553 my_trace_put(buf, &i, c->conn_str, c->conn_str_len);
554 if (type == 'r')
555 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);
562 if (type == 'r')
563 my_trace_put_bool(buf, &i, c->ret);
564 /* TODO
565 } else if (strcmp(func, "mysqli_prepare") == 0) {
566 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);
570 if (type == 'r')
571 my_trace_put_bool(buf, &i, c->ret);
572 */
573 } else if (strcmp(func, "mysqli_query") == 0) {
574 struct query *q = va_arg(va, struct query *);
575 my_trace_put64(buf, &i, (uint64_t) q->dbh);
576 my_trace_put16(buf, &i, q->q_len);
577 my_trace_put(buf, &i, q->q, q->q_len);
578 if (type == 'r')
579 my_trace_put64(buf, &i, (uint64_t) q->res);
482 580 } break; } break;
483 581
484 582 case 'n': case 'n':
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
539 637 if (ret == -1) if (ret == -1)
540 638 my_trace_put32(buf, &i, save_errno); my_trace_put32(buf, &i, save_errno);
541 639 } }
640 } else if (strcmp(func, "pg_close") == 0) {
641 uint64_t h = va_arg(va, uint64_t); // handle
642 my_trace_put64(buf, &i, h);
643 } else if ((strcmp(func, "pg_connect") == 0)
644 || (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);
649 if (type == 'r')
650 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
651 } 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
654 } else if ((strcmp(func, "pg_query") == 0)
655 || (strcmp(func, "pg_query_params") == 0)
656 || (strcmp(func, "pg_send_query") == 0)
657 || (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);
663 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++) {
671 my_trace_put8(buf, &i, pa->type);
672 if (pa->type == ND_PARAMS_TYPE_LONG) {
673 my_trace_put64(buf, &i, pa->l);
674 } else if (pa->type == ND_PARAMS_TYPE_DOUBLE) {
675 my_trace_put_double(buf, &i, pa->d);
676 } else if (pa->type == ND_PARAMS_TYPE_STRING) {
677 my_trace_put16(buf, &i, pa->length);
678 my_trace_put(buf, &i, pa->str, pa->length);
679 }
680 pa++;
681 }
682 }
683 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
687 }
688 } 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
692 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
696 }
542 697 } break; } break;
543 698
544 699 case 'r': case 'r':
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
557 712 if (max > 128) if (max > 128)
558 713 max = 128; max = 128;
559 714 my_trace_put16(buf, &i, max); my_trace_put16(buf, &i, max);
560 memcpy(buf + i, buf2, max); i += max; // data
715 my_trace_put(buf, &i, buf2, max); // data
561 716 } }
562 717 if (ret == -1) if (ret == -1)
563 718 my_trace_put32(buf, &i, save_errno); my_trace_put32(buf, &i, save_errno);
564 719 } }
720 } else if (strcmp(func, "recvfrom") == 0) {
721 my_trace_put32(buf, &i, va_arg(va, int)); // sock
722 struct sockaddr *addr = NULL;
723 my_trace_put64(buf, &i, va_arg(va, uint64_t)); // len
724 if (type == 'r')
725 addr = va_arg(va, void *);
726 socklen_t addrlen = va_arg(va, socklen_t);
727 if (!addr)
728 addrlen = 0;
729 my_trace_put32(buf, &i, addrlen);
730 int flags = va_arg(va, int);
731 my_trace_put32(buf, &i, flags);
732 if (type == 'r') {
733 ssize_t ret = va_arg(va, ssize_t);
734 my_trace_put64(buf, &i, ret);
735 if (ret == -1) {
736 my_trace_put32(buf, &i, save_errno);
737 } else if (ret > 0) { // TODO: not sure if ret is 0 if addr is filled or not
738 unsigned short max = ret;
739 if (max > 128) max = 128;
740 my_trace_put16(buf, &i, max);
741 void *buf = va_arg(va, void *);
742 my_trace_put(buf, &i, buf, max);
743 if (addrlen)
744 my_trace_put(buf, &i, addr, addrlen);
745 }
746 }
565 747 } break; } break;
566 748
567 749 case 's': case 's':
568 750 if (strcmp(func, "send") == 0) { if (strcmp(func, "send") == 0) {
751 const void *data = NULL;
569 752 my_trace_put32(buf, &i, va_arg(va, int)); // sock my_trace_put32(buf, &i, va_arg(va, int)); // sock
570 const void *data = va_arg(va, void *);
753 if (type == 'c')
754 data = va_arg(va, void *);
571 755 size_t len = va_arg(va, size_t); size_t len = va_arg(va, size_t);
572 756 my_trace_put64(buf, &i, len); my_trace_put64(buf, &i, len);
573 757 my_trace_put32(buf, &i, va_arg(va, ssize_t)); // flags my_trace_put32(buf, &i, va_arg(va, ssize_t)); // flags
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
623 807 my_trace_put32(buf, &i, va_arg(va, int)); // domain my_trace_put32(buf, &i, va_arg(va, int)); // domain
624 808 my_trace_put32(buf, &i, va_arg(va, int)); // type my_trace_put32(buf, &i, va_arg(va, int)); // type
625 809 my_trace_put32(buf, &i, va_arg(va, int)); // protocol my_trace_put32(buf, &i, va_arg(va, int)); // protocol
810 int ret = va_arg(va, int);
811 my_trace_put32(buf, &i, ret);
812 if (ret == -1)
813 my_trace_put32(buf, &i, save_errno);
814 } else if (strcmp(func, "sqlite3_open_v2") == 0) {
815 char *filename = va_arg(va, char *);
816 uint16_t filename_len = strlen(filename);
817 my_trace_put16(buf, &i, filename_len);
818 if (filename_len) my_trace_put(buf, &i, filename, filename_len);
819 // TODO: test for zero should be put in the function
820 uint64_t pdb;
821 if (type == 'r')
822 pdb = va_arg(va, uint64_t);
823 my_trace_put32(buf, &i, va_arg(va, int)); // flags
824 char *vfs = va_arg(va, char *);
825 uint16_t vfs_len = vfs ? strlen(vfs) : 0;
826 my_trace_put16(buf, &i, vfs_len);
827 if (vfs_len) my_trace_put(buf, &i, vfs, vfs_len);
626 828 if (type == 'r') { if (type == 'r') {
627 829 int ret = va_arg(va, int); int ret = va_arg(va, int);
628 830 my_trace_put32(buf, &i, ret); my_trace_put32(buf, &i, ret);
629 if (ret == -1)
630 my_trace_put32(buf, &i, save_errno);
831 if (ret == 0)
832 my_trace_put64(buf, &i, pdb);
631 833 } }
834 } else if (strcmp(func, "sqlite3_prepare_v2") == 0) {
835 uint64_t h = va_arg(va, uint64_t);
836 my_trace_put64(buf, &i, h);
837 char *sql = va_arg(va, char *);
838 uint32_t sql_len = strlen(sql);
839 my_trace_put32(buf, &i, sql_len);
840 if (sql_len) my_trace_put(buf, &i, sql, sql_len);
841 my_trace_put32(buf, &i, va_arg(va, int)); // nByte
842 if (type == 'r') {
843 my_trace_put64(buf, &i, va_arg(va, uint64_t)); // stmt
844 my_trace_put32(buf, &i, va_arg(va, int)); // ret
845 }
846 } else if (strcmp(func, "sqlite3_step") == 0) {
847 uint64_t stmt = va_arg(va, uint64_t);
848 my_trace_put64(buf, &i, stmt);
849 if (type == 'r')
850 my_trace_put32(buf, &i, va_arg(va, int)); // ret
632 851 } else if (strcmp(func, "stat") == 0) { } else if (strcmp(func, "stat") == 0) {
633 852 char *pathname = va_arg(va, char *); char *pathname = va_arg(va, char *);
634 853 unsigned short len = strlen(pathname); unsigned short len = strlen(pathname);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
696 915 return i; return i;
697 916 } }
698 917
699 static void my_trace(const char *func, const char type, ...)
918 void my_trace(const char *func, const char type, ...)
700 919 { {
701 920 int save_errno; int save_errno;
702 921 va_list va; va_list va;
 
... ... static void my_trace(const char *func, const char type, ...)
710 929
711 930 save_errno = errno; save_errno = errno;
712 931
713 xlog(0, "%s func=%s type=%c errno=%d\n", __func__, func, type, errno);
932 xlog(200, "%s func=%s type=%c errno=%d\n",
933 __func__, func, type, errno);
714 934
715 935 locked = 0; locked = 0;
716 936 do { do {
 
... ... static void my_trace(const char *func, const char type, ...)
721 941 i = my_trace_encode(out, func, type, save_errno, va); i = my_trace_encode(out, func, type, save_errno, va);
722 942 va_end(va); va_end(va);
723 943 if (i == 0) { if (i == 0) {
724 xlog(0, "I do not know how to encode [%s][%c]!\n", func, type);
944 xlog(1, "I do not know how to encode [%s][%c]!\n", func, type);
725 945 break; break;
726 946 } }
727 947
728 948 char dump[i * 4 + 1]; char dump[i * 4 + 1];
729 949 bin2hex_ascii(dump, out, i); bin2hex_ascii(dump, out, i);
730 xlog(0, " gen: %s\n", dump);
950 xlog(201, " gen: %s\n", dump);
731 951
732 xlog(0, " head=%u tail=%u to_copy=%u [start]\n",
952 // TODO: use an internal buffer if we cannot take the lock and move back to 'trywait'
953 xlog(201, " head=%u tail=%u to_copy=%u [start]\n",
733 954 shared->head, shared->tail, i); shared->head, shared->tail, i);
734 r = sem_trywait(&shared->sem1);
955 r = sem_wait(&shared->sem1);
735 956 if (r == -1) { if (r == -1) {
736 xlog(0, "sem_trywait sem1 error: %m\n");
957 xlog(1, "sem_trywait sem1 error: %m\n");
737 958 break; break;
738 959 } }
739 960 locked = 1; locked = 1;
 
... ... static void my_trace(const char *func, const char type, ...)
748 969 ava = shared->head - shared->tail; ava = shared->head - shared->tail;
749 970 } }
750 971 if (ava < i) { if (ava < i) {
751 xlog(0, "%s: not enough available: ava[%u] < i[%u]\n",
972 xlog(1, "%s: not enough available: ava[%u] < i[%u]\n",
752 973 __func__, ava, i); __func__, ava, i);
753 974 shared->msgs_lost++; // TODO: add to an internal buffer shared->msgs_lost++; // TODO: add to an internal buffer
754 975 break; break;
755 976 } }
756 unsigned int max = shared->buf_size - shared->tail; // size=11 tail=5 max=6: .....t.....
977 unsigned int max = shared->buf_size - shared->tail; // size=11 tail=5 max=6: .....t.....
757 978 if (max > i) { // enough space if (max > i) { // enough space
758 979 memcpy(shared->buf + shared->tail, out, i); memcpy(shared->buf + shared->tail, out, i);
759 980 shared->tail += i; shared->tail += i;
 
... ... static void my_trace(const char *func, const char type, ...)
762 983 memcpy(shared->buf, out + max, i - max); memcpy(shared->buf, out + max, i - max);
763 984 shared->tail = i - max; // size=13 head=2 tail=5 i=9 max=8: ..h..t....... => 89h..01234567 => tail=1 shared->tail = i - max; // size=13 head=2 tail=5 i=9 max=8: ..h..t....... => 89h..01234567 => tail=1
764 985 } }
765
766 shared->tail = shared->tail;
767
768 986 } while (0); } while (0);
769 987
770 988 if (locked) { if (locked) {
771 989 r = sem_post(&shared->sem1); // was sem2 r = sem_post(&shared->sem1); // was sem2
772 990 if (r == -1) if (r == -1)
773 xlog(0, "sem_post sem1 error: %m\n");
991 xlog(1, "sem_post sem1 error: %m\n");
774 992
775 xlog(0, " head=%u tail=%u shared->tail=%u [got lock]\n",
776 shared->head, shared->tail, shared->tail);
993 xlog(201, " head=%u tail=%u [got lock]\n",
994 shared->head, shared->tail);
777 995 } }
778 996
997 if (type == 'c')
998 trace_depth++;
999 else if (type == 'r')
1000 trace_depth--;
1001
779 1002 errno = save_errno; errno = save_errno;
780 1003 } }
781 1004
782 1005 static void my_on_exit(int ret, void *junk) static void my_on_exit(int ret, void *junk)
783 1006 { {
784 1007 xlog(100, "my_on_exit ret=%d junk=%p!\n", ret, junk); xlog(100, "my_on_exit ret=%d junk=%p!\n", ret, junk);
785 my_trace("-stop", 'r', ret);
1008 my_trace("-stop", 'R', ret);
786 1009 ninedogs_process_core(NINEDOGS_CORE_STOP, &ret); ninedogs_process_core(NINEDOGS_CORE_STOP, &ret);
787 1010 } }
788 1011
 
... ... void _exit(int status)
791 1014 { {
792 1015 //write(1, "_exit\n", 6); //write(1, "_exit\n", 6);
793 1016 xlog(1, "my _exit status=%d!\n", status); xlog(1, "my _exit status=%d!\n", status);
794 my_trace("-stop", 'r', status);
1017 my_trace("-stop", 'R', status);
795 1018 old__exit(status); old__exit(status);
796 1019 } }
797 1020 #endif #endif
 
... ... static void my_segv(int sig)
811 1034 for (int j = 0; j < r; j++) for (int j = 0; j < r; j++)
812 1035 xlog(0, " %s\n", a[j]); xlog(0, " %s\n", a[j]);
813 1036 } }
814 my_trace("-segv", 'r', a, r);
1037 my_trace("-segv", 'R', a, r);
815 1038
816 1039 exit(1); exit(1);
817 1040 } }
 
... ... static void ninedogs_child(void)
877 1100
878 1101 __attribute__((destructor)) void ninedogs_fini(void) __attribute__((destructor)) void ninedogs_fini(void)
879 1102 { {
880 xlog(0, "%s\n", __func__);
1103 xlog(20, "%s\n", __func__);
881 1104 //my_trace("-dest", "r"); //my_trace("-dest", "r");
882 1105 if (shared_inited) { if (shared_inited) {
883 1106 char name[128]; char name[128];
 
... ... __attribute__((constructor)) void ninedogs_init(void)
916 1139 return; return;
917 1140
918 1141 //write(1, "ninedogs: init start\n", 21); //write(1, "ninedogs: init start\n", 21);
919 dlh = dlmopen(LM_ID_BASE, "/date/sync/no-crypt/sync1/Dev/ninedogs/agent/ninedogs_dlsym_env.so",
1142 dlh = dlmopen(LM_ID_BASE, "/usr/lib64/ninedogs_dlsym_env.so",
920 1143 RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND); RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
1144 if (!dlh)
1145 dlh = dlmopen(LM_ID_BASE, "/usr/lib/ninedogs_dlsym_env.so",
1146 RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
1147 if (!dlh)
1148 dlh = dlmopen(LM_ID_BASE, "/date/sync/no-crypt/sync1/Dev/ninedogs/agent/ninedogs_dlsym_env.so",
1149 RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
921 1150 //write(1, "ae\n", 3); //write(1, "ae\n", 3);
922 1151 if (!dlh) if (!dlh)
923 1152 exit(1); exit(1);
 
... ... __attribute__((constructor)) void ninedogs_init(void)
1183 1412 exit(1); exit(1);
1184 1413 } }
1185 1414
1415 old_fork = old_dlsym(RTLD_NEXT, "fork");
1416 if (old_fork == NULL) {
1417 xlog(0, " cannot resolve 'fork'!\n");
1418 exit(1);
1419 }
1420
1186 1421
1187 1422 x = getenv("NINEDOGS_VERBOSE"); x = getenv("NINEDOGS_VERBOSE");
1188 1423 if (x != NULL) if (x != NULL)
 
... ... __attribute__((constructor)) void ninedogs_init(void)
1214 1449 xlog(0, "Cannot do mmap: %m\n"); xlog(0, "Cannot do mmap: %m\n");
1215 1450 break; break;
1216 1451 } }
1217 xlog(0, "%s: shared=%p\n", __func__, shared);
1452 xlog(200, "%s: shared=%p\n", __func__, shared);
1218 1453
1219 1454 if (sem_init(&shared->sem1, 1, 1) == -1) { if (sem_init(&shared->sem1, 1, 1) == -1) {
1220 1455 xlog(0, "Cannot do sem_init sem1: %m\n"); xlog(0, "Cannot do sem_init sem1: %m\n");
1221 1456 break; break;
1222 1457 } }
1223 1458
1459 shared->version = SHARED_VERSION;
1224 1460 shared->buf_size = sizeof(shared->buf); shared->buf_size = sizeof(shared->buf);
1225 1461 shared->msgs_lost = 0; shared->msgs_lost = 0;
1226 1462 // We want force from start start the wrap around // We want force from start start the wrap around
 
... ... __attribute__((constructor)) void ninedogs_init(void)
1239 1475 x = getenv("JAVA_TOOL_OPTIONS"); x = getenv("JAVA_TOOL_OPTIONS");
1240 1476 if (!x) if (!x)
1241 1477 x = ""; x = "";
1242 snprintf(env, sizeof(env), "-javaagent:../../../agent/java/agent/ninedogs-agent.jar %s", x);
1478 snprintf(env, sizeof(env), "-javaagent:/usr/share/ninedogs/ninedogs-agent.jar %s", x);
1243 1479 setenv("JAVA_TOOL_OPTIONS", env, 1); setenv("JAVA_TOOL_OPTIONS", env, 1);
1244 1480
1245 1481 /* .NET stuff */ /* .NET stuff */
 
... ... __attribute__((constructor)) void ninedogs_init(void)
1255 1491
1256 1492 ninedogs_process_core(NINEDOGS_CORE_START, NULL); ninedogs_process_core(NINEDOGS_CORE_START, NULL);
1257 1493
1494 xlog(100, "%s: done; my pid %d\n", __func__, getpid());
1258 1495 } }
1259 1496
1260 1497 void *realloc(void *ptr, size_t size) void *realloc(void *ptr, size_t size)
 
... ... int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
1407 1644 return -1; return -1;
1408 1645
1409 1646 saddr(tmp, sizeof(tmp), (struct sockaddr *) addr); saddr(tmp, sizeof(tmp), (struct sockaddr *) addr);
1410 xlog(1, "bind(sockfd=%d, %s)\n", sockfd, tmp);
1647 xlog(100, "bind(sockfd=%d, %s)\n", sockfd, tmp);
1411 1648
1412 1649 memcpy(&new, addr, addrlen); memcpy(&new, addr, addrlen);
1413 1650
 
... ... int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
1424 1661 } while (0); } while (0);
1425 1662
1426 1663 ret = old_bind(sockfd, (struct sockaddr *) &new, addrlen); ret = old_bind(sockfd, (struct sockaddr *) &new, addrlen);
1427 my_trace(__func__, 'r', sockfd, &new, addrlen, ret);
1664 my_trace(__func__, 'R', sockfd, &new, addrlen, ret);
1428 1665
1429 1666 return ret; return ret;
1430 1667 } }
 
... ... int socket(int domain, int type, int protocol)
1495 1732 { {
1496 1733 int sockfd; int sockfd;
1497 1734
1498 xlog(50, "socket(domain=%s[%d], type=%s, protocol=%s)\n",
1735 xlog(100, "socket(domain=%s[%d], type=%s, protocol=%s)\n",
1499 1736 sdomain(domain), domain, stype(type), sprotocol(protocol)); sdomain(domain), domain, stype(type), sprotocol(protocol));
1500 1737
1501 1738 sockfd = old_socket(domain, type, protocol); sockfd = old_socket(domain, type, protocol);
1502 1739 //if (sockfd != -1) //if (sockfd != -1)
1503 1740 // socket_create_callback(sockfd, domain, type); // socket_create_callback(sockfd, domain, type);
1504
1505 my_trace(__func__, 'r', domain, type, protocol, sockfd);
1741 my_trace(__func__, 'R', domain, type, protocol, sockfd);
1506 1742
1507 1743 return sockfd; return sockfd;
1508 1744 } }
 
... ... int close(int fd)
1519 1755 //del(fd); //del(fd);
1520 1756 fd_del(fd); fd_del(fd);
1521 1757
1758 my_trace(__func__, 'c', fd);
1522 1759 ret = old_close(fd); ret = old_close(fd);
1523
1524 1760 my_trace(__func__, 'r', fd, ret); my_trace(__func__, 'r', fd, ret);
1525 1761
1526 1762 return ret; return ret;
 
... ... ssize_t send(int sockfd, const void *buf, size_t len, int flags)
1577 1813 struct node *q; struct node *q;
1578 1814 ssize_t ret; ssize_t ret;
1579 1815
1580 xlog(50, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n",
1816 xlog(110, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n",
1581 1817 __func__, sockfd, len, flags); __func__, sockfd, len, flags);
1582 1818
1583 1819 /* We do not touch non network sockets */ /* We do not touch non network sockets */
 
... ... ssize_t send(int sockfd, const void *buf, size_t len, int flags)
1587 1823 } }
1588 1824
1589 1825 my_trace(__func__, 'c', sockfd, buf, len, flags); my_trace(__func__, 'c', sockfd, buf, len, flags);
1590
1591 1826 ret = old_send(sockfd, buf, len, flags); ret = old_send(sockfd, buf, len, flags);
1592
1593 1827 my_trace(__func__, 'r', sockfd, len, flags, ret); my_trace(__func__, 'r', sockfd, len, flags, ret);
1594 1828
1595 1829 return ret; return ret;
 
... ... ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
1601 1835 struct node *q; struct node *q;
1602 1836 ssize_t ret; ssize_t ret;
1603 1837
1604 xlog(50, "sendto(sockfd, %d, buf, len=%zu, flags=0x%x, ...)\n",
1838 xlog(110, "sendto(sockfd, %d, buf, len=%zu, flags=0x%x, ...)\n",
1605 1839 sockfd, len, flags); sockfd, len, flags);
1606 1840
1607 1841 /* We do not touch non network sockets */ /* We do not touch non network sockets */
 
... ... ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
1611 1845 } }
1612 1846
1613 1847 my_trace(__func__, 'c', sockfd, buf, len, flags, dest_addr, addrlen); my_trace(__func__, 'c', sockfd, buf, len, flags, dest_addr, addrlen);
1614
1615 1848 ret = old_sendto(sockfd, buf, len, flags, dest_addr, addrlen); ret = old_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
1616
1617 1849 my_trace(__func__, 'r', sockfd, len, flags, ret); my_trace(__func__, 'r', sockfd, len, flags, ret);
1618 1850
1619 1851 return ret; return ret;
 
... ... ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
1629 1861 struct sockaddr_storage new_dest; struct sockaddr_storage new_dest;
1630 1862 */ */
1631 1863
1632 xlog(50, "sendmsg(sockfd=%d, ..., flags=0x%x)\n",
1864 xlog(100, "sendmsg(sockfd=%d, ..., flags=0x%x)\n",
1633 1865 sockfd, flags); sockfd, flags);
1634 1866
1635 1867 /* TODO: log also this! */ /* TODO: log also this! */
 
... ... ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
1637 1869 dump(200, "sendmsg", msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); dump(200, "sendmsg", msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
1638 1870
1639 1871 my_trace(__func__, 'c', sockfd, msg, flags); my_trace(__func__, 'c', sockfd, msg, flags);
1640
1641 1872 ret = old_sendmsg(sockfd, msg, flags); ret = old_sendmsg(sockfd, msg, flags);
1642 1873 xlog(50, " returned %zd\n", ret); xlog(50, " returned %zd\n", ret);
1643
1644 1874 my_trace(__func__, 'r', sockfd, flags, ret); my_trace(__func__, 'r', sockfd, flags, ret);
1645 1875
1646 1876 return ret; return ret;
 
... ... ssize_t recv(int sockfd, void *buf, size_t len, int flags)
1651 1881 struct node *q; struct node *q;
1652 1882 ssize_t ret; ssize_t ret;
1653 1883
1654 xlog(50, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n",
1884 xlog(110, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n",
1655 1885 __func__, sockfd, len, flags); __func__, sockfd, len, flags);
1656 1886
1657 1887 my_trace(__func__, 'c', sockfd, len, flags); my_trace(__func__, 'c', sockfd, len, flags);
1658
1659 1888 ret = old_recv(sockfd, buf, len, flags); ret = old_recv(sockfd, buf, len, flags);
1660
1661 1889 /* We do not touch non network sockets */ /* We do not touch non network sockets */
1662 1890 q = get(sockfd); q = get(sockfd);
1663 1891 if (q && (q->priv.flags & FB_FLAGS_NETSOCK)) { if (q && (q->priv.flags & FB_FLAGS_NETSOCK)) {
 
... ... ssize_t recv(int sockfd, void *buf, size_t len, int flags)
1665 1893 if (ret > 0) if (ret > 0)
1666 1894 dump(200, "recv", buf, ret); dump(200, "recv", buf, ret);
1667 1895 } }
1668
1669 1896 my_trace(__func__, 'r', sockfd, buf, len, flags, ret); my_trace(__func__, 'r', sockfd, buf, len, flags, ret);
1670 1897
1671 1898 return ret; return ret;
 
... ... ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
1678 1905 unsigned int i; unsigned int i;
1679 1906 size_t rest; size_t rest;
1680 1907
1681 xlog(50, "%s(sockfd=%d, msg, flags=0x%x)\n",
1908 xlog(110, "%s(sockfd=%d, msg, flags=0x%x)\n",
1682 1909 __func__, sockfd, flags); __func__, sockfd, flags);
1683 1910
1684 1911 my_trace(__func__, 'c', sockfd, msg, flags); my_trace(__func__, 'c', sockfd, msg, flags);
1685
1686 1912 ret = old_recvmsg(sockfd, msg, flags); ret = old_recvmsg(sockfd, msg, flags);
1687
1688 1913 /* We do not touch non network sockets */ /* We do not touch non network sockets */
1689 1914 q = get(sockfd); q = get(sockfd);
1690 1915 if (q && (q->priv.flags & FB_FLAGS_NETSOCK) && (ret != -1)) { if (q && (q->priv.flags & FB_FLAGS_NETSOCK) && (ret != -1)) {
 
... ... ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
1701 1926 return ret; return ret;
1702 1927 } }
1703 1928
1929 ssize_t recvfrom(int sockfd, void *restrict buf, size_t len, int flags,
1930 struct sockaddr *restrict src_addr, socklen_t *restrict addrlen)
1931 {
1932 ssize_t ret;
1933 //TODO? struct node *q;
1934
1935 my_trace(__func__, 'c', sockfd, len, addrlen ? *addrlen : 0, flags);
1936 ret = old_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
1937 my_trace(__func__, 'r', sockfd, len, src_addr, addrlen ? *addrlen : 0, flags, ret, buf);
1938
1939 return ret;
1940 }
1941
1704 1942 /* /*
1705 1943 * We have to hijack accept because the program may be a daemon. * We have to hijack accept because the program may be a daemon.
1706 1944 */ */
 
... ... int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
1710 1948 struct node *q; struct node *q;
1711 1949 struct private *p; struct private *p;
1712 1950
1713 xlog(2, "accept(sockfd=%d, ...)\n", sockfd);
1951 xlog(100, "accept(sockfd=%d, ...)\n", sockfd);
1714 1952
1715 1953 my_trace(__func__, 'c', sockfd, addrlen ? *addrlen : 0); my_trace(__func__, 'c', sockfd, addrlen ? *addrlen : 0);
1716
1717 1954 new_sock = old_accept(sockfd, addr, addrlen); new_sock = old_accept(sockfd, addr, addrlen);
1718 1955 if (new_sock != -1) { if (new_sock != -1) {
1719 1956 /* We must find out domain and type for accepting socket */ /* We must find out domain and type for accepting socket */
 
... ... int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
1724 1961 socket_create_callback(new_sock, p->domain, p->type); socket_create_callback(new_sock, p->domain, p->type);
1725 1962 } }
1726 1963 } }
1727
1728 1964 my_trace(__func__, 'r', sockfd, addr, addrlen ? *addrlen : 0, new_sock); my_trace(__func__, 'r', sockfd, addr, addrlen ? *addrlen : 0, new_sock);
1729 1965
1730 1966 return new_sock; return new_sock;
 
... ... int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
1739 1975 struct node *q; struct node *q;
1740 1976 struct private *p; struct private *p;
1741 1977
1742 xlog(2, "accept4(sockfd=%d, ...flags=0x%x)\n", sockfd, flags);
1978 xlog(100, "accept4(sockfd=%d, ...flags=0x%x)\n", sockfd, flags);
1743 1979
1744 1980 my_trace(__func__, 'c', sockfd, addrlen ? *addrlen : 0, flags); my_trace(__func__, 'c', sockfd, addrlen ? *addrlen : 0, flags);
1745
1746 1981 new_sock = old_accept4(sockfd, addr, addrlen, flags); new_sock = old_accept4(sockfd, addr, addrlen, flags);
1747 1982 if (new_sock != -1) { if (new_sock != -1) {
1748 1983 /* We must find out domain and type for accepting socket */ /* We must find out domain and type for accepting socket */
 
... ... int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
1753 1988 socket_create_callback(new_sock, p->domain, p->type); socket_create_callback(new_sock, p->domain, p->type);
1754 1989 } }
1755 1990 } }
1756
1757 1991 my_trace(__func__, 'r', sockfd, addr, addrlen ? *addrlen : 0, my_trace(__func__, 'r', sockfd, addr, addrlen ? *addrlen : 0,
1758 1992 flags, new_sock); flags, new_sock);
1759 1993
 
... ... int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
1762 1996
1763 1997 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
1764 1998 { {
1765 struct node *q;
1999 //struct node *q;
1766 2000 int ret; int ret;
1767 2001 char sdest[128]; char sdest[128];
1768 2002
1769 2003 saddr(sdest, sizeof(sdest), addr); saddr(sdest, sizeof(sdest), addr);
1770 xlog(2, "connect(sockfd=%d, %s)\n", sockfd, sdest);
2004 xlog(100, "connect(sockfd=%d, %s)\n", sockfd, sdest);
1771 2005
1772 q = get(sockfd);
1773 if (q)
1774 gettimeofday(&q->priv.conn_time, NULL);
2006 // TODO
2007 //q = get(sockfd);
2008 //if (q)
2009 // gettimeofday(&q->priv.conn_time, NULL);
1775 2010
1776 2011 my_trace(__func__, 'c', sockfd, addr, addrlen); my_trace(__func__, 'c', sockfd, addr, addrlen);
1777
1778 2012 ret = old_connect(sockfd, addr, addrlen); ret = old_connect(sockfd, addr, addrlen);
1779 2013 if (ret == 0) { if (ret == 0) {
1780 struct timeval e, f;
2014 //struct timeval e, f;
1781 2015
1782 gettimeofday(&e, NULL);
1783 my_time_diff(&f, &e, &q->priv.conn_time);
1784 xlog(3, " took %u.%03u\n", f.tv_sec, f.tv_usec / 1000);
2016 //gettimeofday(&e, NULL);
2017 //my_time_diff(&f, &e, &q->priv.conn_time);
2018 //xlog(100, " took %u.%03u\n", f.tv_sec, f.tv_usec / 1000);
1785 2019 } else { } else {
1786 xlog(3, " failed: %m\n");
2020 xlog(100, " failed: %m\n");
1787 2021 } }
1788
1789 2022 my_trace(__func__, 'r', sockfd, ret); my_trace(__func__, 'r', sockfd, ret);
1790 2023
1791 2024 return ret; return ret;
 
... ... int poll(struct pollfd *fds, nfds_t nfds, int timeout)
1795 2028 { {
1796 2029 int ret; int ret;
1797 2030
1798 xlog(40, "poll(fds, %d, %d)\n", nfds, timeout);
2031 xlog(100, "poll(fds, %d, %d)\n", nfds, timeout);
1799 2032
1800 2033 my_trace(__func__, 'c', fds, nfds, timeout); my_trace(__func__, 'c', fds, nfds, timeout);
1801
1802 2034 ret = old_poll(fds, nfds, timeout); ret = old_poll(fds, nfds, timeout);
1803
1804 2035 my_trace(__func__, 'r', fds, nfds, timeout, ret); my_trace(__func__, 'r', fds, nfds, timeout, ret);
1805 2036
1806 2037 return ret; return ret;
 
... ... struct hostent *gethostbyname(const char *name)
1810 2041 { {
1811 2042 struct hostent *ret; struct hostent *ret;
1812 2043
1813 xlog(2, "gethostbyname(%s)\n", name);
2044 xlog(100, "gethostbyname(%s)\n", name);
1814 2045
1815 2046 my_trace(__func__, 'c', name); my_trace(__func__, 'c', name);
1816
1817 2047 ret = old_gethostbyname(name); ret = old_gethostbyname(name);
1818
1819 2048 my_trace(__func__, 'r', name, ret); my_trace(__func__, 'r', name, ret);
1820 2049
1821 2050 return ret; return ret;
 
... ... int getaddrinfo(const char *restrict node, const char *restrict service,
1826 2055 { {
1827 2056 int ret; int ret;
1828 2057
1829 xlog(2, "getaddrinfo(node=%s, service=%s, hints=0x%x)\n",
2058 xlog(100, "getaddrinfo(node=%s, service=%s, hints=0x%x)\n",
1830 2059 node, service, hints ? hints : 0); node, service, hints ? hints : 0);
1831 2060
1832 2061 my_trace(__func__, 'c', node, service, hints); my_trace(__func__, 'c', node, service, hints);
1833
1834 2062 ret = old_getaddrinfo(node, service, hints, res); ret = old_getaddrinfo(node, service, hints, res);
1835
1836 2063 my_trace(__func__, 'r', node, service, hints, res, ret); my_trace(__func__, 'r', node, service, hints, res, ret);
1837 2064
1838 2065 return ret; return ret;
1839 2066 } }
1840 2067
2068 // TODO: not yet in trace
1841 2069 int pthread_create(pthread_t *restrict thread, int pthread_create(pthread_t *restrict thread,
1842 2070 const pthread_attr_t *restrict attr, void *(*start_routine)(void *), const pthread_attr_t *restrict attr, void *(*start_routine)(void *),
1843 2071 void *restrict arg) void *restrict arg)
 
... ... int pthread_create(pthread_t *restrict thread,
1847 2075 //xlog(2, "pthread_create\n"); //xlog(2, "pthread_create\n");
1848 2076
1849 2077 ret = old_pthread_create(thread, attr, start_routine, arg); ret = old_pthread_create(thread, attr, start_routine, arg);
1850 my_trace(__func__, 'r', thread, attr, arg, ret);
2078 my_trace(__func__, 'R', thread, attr, arg, ret);
1851 2079
1852 2080 return ret; return ret;
1853 2081 } }
 
... ... int pthread_join(pthread_t thread, void **retval)
1859 2087 //xlog(2, "pthread_join\n"); //xlog(2, "pthread_join\n");
1860 2088
1861 2089 ret = old_pthread_join(thread, retval); ret = old_pthread_join(thread, retval);
1862 my_trace(__func__, 'r', retval, ret);
2090 my_trace(__func__, 'R', retval, ret);
1863 2091
1864 2092 return ret; return ret;
1865 2093 } }
 
... ... int pthread_attr_init(pthread_attr_t *attr)
1873 2101 xlog(2, "%s\n", __func__); xlog(2, "%s\n", __func__);
1874 2102
1875 2103 ret = old_pthread_attr_init(attr); ret = old_pthread_attr_init(attr);
1876 my_trace(__func__, 'r', attr, ret);
2104 my_trace(__func__, 'R', attr, ret);
1877 2105
1878 2106 return ret; return ret;
1879 2107 } }
 
... ... int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
1885 2113 //xlog(2, "pthread_attr_setstacksize(%zu)\n", stacksize); //xlog(2, "pthread_attr_setstacksize(%zu)\n", stacksize);
1886 2114
1887 2115 ret = old_pthread_attr_setstacksize(attr, stacksize); ret = old_pthread_attr_setstacksize(attr, stacksize);
1888
1889 my_trace(__func__, 'r', attr, stacksize, ret);
2116 my_trace(__func__, 'R', attr, stacksize, ret);
1890 2117
1891 2118 return ret; return ret;
1892 2119 } }
1893 2120
2121 // TODO: not yet in tracing (done on nd-trace)
1894 2122 int getsockopt(int sockfd, int level, int optname, void *restrict optval, int getsockopt(int sockfd, int level, int optname, void *restrict optval,
1895 2123 socklen_t *restrict optlen) socklen_t *restrict optlen)
1896 2124 { {
 
... ... int getsockopt(int sockfd, int level, int optname, void *restrict optval,
1919 2147 break; break;
1920 2148 } }
1921 2149
1922 my_trace(__func__, 'r', sockfd, level, optname, optval, optlen, r);
2150 my_trace(__func__, 'R', sockfd, level, optname, optval, *optlen, r);
1923 2151
1924 2152 return r; return r;
1925 2153 } }
 
... ... int open(const char *pathname, int flags, ...)
1950 2178 if (ret == -1) if (ret == -1)
1951 2179 return -1; return -1;
1952 2180 struct fd_node *q = fd_add(ret); struct fd_node *q = fd_add(ret);
2181 if (q) {
1953 2182 q->flags |= FD_NODE_DEV_NINEDOGS; q->flags |= FD_NODE_DEV_NINEDOGS;
1954 xlog(0, "APP Metrics opened fd=%d flags=0x%08x\n",
1955 ret, q->flags);
2183 xlog(0, "APP Metrics opened fd=%d flags=0x%08x\n",
2184 ret, q->flags);
2185 }
1956 2186 return ret; return ret;
1957 2187 } }
1958 2188
 
... ... int open(const char *pathname, int flags, ...)
1962 2192 va_end(va); va_end(va);
1963 2193 } }
1964 2194
1965 my_trace(__func__, 'c', pathname, flags, mode);
1966
1967 2195 xlog(20, "%s(%s, %d, %d)\n", __func__, pathname, flags, mode); xlog(20, "%s(%s, %d, %d)\n", __func__, pathname, flags, mode);
2196 my_trace(__func__, 'c', pathname, flags, mode);
1968 2197 ret = old_open(pathname, flags, mode); ret = old_open(pathname, flags, mode);
1969 xlog(25, " ret=%d\n", ret);
1970
1971 2198 my_trace(__func__, 'r', pathname, flags, mode, ret); my_trace(__func__, 'r', pathname, flags, mode, ret);
2199 xlog(25, " ret=%d\n", ret);
1972 2200
1973 2201 return ret; return ret;
1974 2202 } }
 
... ... int open64(const char *pathname, int flags, ...)
1996 2224 va_end(va); va_end(va);
1997 2225 } }
1998 2226
1999 xlog(20, "%s(%s, %d, %d)\n", __func__, pathname, flags, mode);
2227 xlog(100, "%s(%s, %d, %d)\n", __func__, pathname, flags, mode);
2228 my_trace(__func__, 'c', pathname, flags, mode);
2000 2229 ret = old_open64(pathname, flags, mode); ret = old_open64(pathname, flags, mode);
2001 xlog(25, " ret=%d\n", ret);
2002
2003 2230 my_trace(__func__, 'r', pathname, flags, mode, ret); my_trace(__func__, 'r', pathname, flags, mode, ret);
2231 xlog(101, " ret=%d\n", ret);
2004 2232
2005 2233 return ret; return ret;
2006 2234 } }
 
... ... int openat(int dirfd, const char *pathname, int flags, ...)
2012 2240 va_list va; va_list va;
2013 2241
2014 2242 if (strcmp(pathname, "/dev/ninedogs") == 0) { if (strcmp(pathname, "/dev/ninedogs") == 0) {
2015 ret = old_open64("/dev/null", O_WRONLY);
2243 ret = old_openat(0, "/dev/null", O_WRONLY);
2016 2244 if (ret == -1) if (ret == -1)
2017 2245 return -1; return -1;
2018 2246 struct fd_node *q = fd_add(ret); struct fd_node *q = fd_add(ret);
 
... ... int openat(int dirfd, const char *pathname, int flags, ...)
2029 2257 } }
2030 2258
2031 2259 xlog(20, "%s(%d, %s, %d, %d)\n", __func__, dirfd, pathname, flags, mode); xlog(20, "%s(%d, %s, %d, %d)\n", __func__, dirfd, pathname, flags, mode);
2260 my_trace(__func__, 'c', dirfd, pathname, flags, mode);
2032 2261 ret = old_openat(dirfd, pathname, flags, mode); ret = old_openat(dirfd, pathname, flags, mode);
2033 xlog(25, " ret=%d\n", ret);
2034
2035 2262 my_trace(__func__, 'r', dirfd, pathname, flags, mode, ret); my_trace(__func__, 'r', dirfd, pathname, flags, mode, ret);
2263 xlog(25, " ret=%d\n", ret);
2036 2264
2037 2265 return ret; return ret;
2038 2266 } }
2039 2267
2268 #if 0
2269 // TODO: remove this
2040 2270 static int my_stat(const char *restrict pathname, struct stat *restrict statbuf) static int my_stat(const char *restrict pathname, struct stat *restrict statbuf)
2041 2271 { {
2042 2272 int ret; int ret;
2043 2273
2044 2274 xlog(20, "%s(%s, %p)\n", __func__, pathname, statbuf); xlog(20, "%s(%s, %p)\n", __func__, pathname, statbuf);
2275 my_trace(__func__, 'c', pathname, statbuf);
2045 2276 ret = old_stat(pathname, statbuf); ret = old_stat(pathname, statbuf);
2046 xlog(25, " ret=%d\n", ret);
2047
2048 2277 my_trace(__func__, 'r', pathname, statbuf, ret); my_trace(__func__, 'r', pathname, statbuf, ret);
2278 xlog(25, " ret=%d\n", ret);
2049 2279
2050 2280 return ret; return ret;
2051 2281 } }
2282 #endif
2052 2283
2053 2284 void *dlsym(void *restrict handle, const char *restrict symbol) void *dlsym(void *restrict handle, const char *restrict symbol)
2054 2285 { {
 
... ... void *dlsym(void *restrict handle, const char *restrict symbol)
2061 2292 ret = old_dlsym(handle, symbol); ret = old_dlsym(handle, symbol);
2062 2293 xlog(50, "%s(%p, %s) = %p\n", __func__, handle, symbol, ret); xlog(50, "%s(%p, %s) = %p\n", __func__, handle, symbol, ret);
2063 2294
2064 if (ret) {
2065 if (strcmp(symbol, "get_module") == 0)
2066 ret = php_hook(ret);
2067 //else if (strcmp(symbol, "open") == 0)
2068 // ret = my_open;
2069 else if (strcmp(symbol, "stat") == 0)
2070 ret = my_stat;
2071 }
2295 if (!ret)
2296 return NULL;
2297
2298 if (strcmp(symbol, "get_module") == 0)
2299 ret = php_hook(ret);
2300 //else if (strcmp(symbol, "open") == 0)
2301 // ret = my_open;
2302 //else if (strcmp(symbol, "stat") == 0)
2303 // ret = my_stat;
2304 else if (strncmp(symbol, "PyInit__", 8) == 0)
2305 return python_hook(symbol, ret);
2072 2306
2073 2307 return ret; return ret;
2074 2308 } }
 
... ... void *dlopen(const char *filename, int flags)
2080 2314 if (!old_dlopen) if (!old_dlopen)
2081 2315 return NULL; return NULL;
2082 2316
2317 my_trace(__func__, 'c', filename, flags);
2083 2318 ret = old_dlopen(filename, flags); ret = old_dlopen(filename, flags);
2319 my_trace(__func__, 'r', filename, flags, ret);
2084 2320 xlog(100, "%s(%s, 0x%x) = %p\n", __func__, filename, flags, ret); xlog(100, "%s(%s, 0x%x) = %p\n", __func__, filename, flags, ret);
2085 if (!ret) {
2321 if (ret) {
2086 2322 // TODO: should I add only 'flags=GLOBAL' entries? // TODO: should I add only 'flags=GLOBAL' entries?
2323 unsigned found = 0, first_free = DLOPEN_MAX_ENTRIES;
2087 2324 for (unsigned i = 0; i < DLOPEN_MAX_ENTRIES; i++) { for (unsigned i = 0; i < DLOPEN_MAX_ENTRIES; i++) {
2088 if (filename == NULL)
2089 break;
2090
2091 2325 if (dlopen_nodes[i].p == ret) { if (dlopen_nodes[i].p == ret) {
2326 xlog(101, "%s: path [%s] already stored in pos %u\n",
2327 __func__, filename, i);
2092 2328 dlopen_nodes[i].count++; dlopen_nodes[i].count++;
2329 found = 1;
2093 2330 break; break;
2094 2331 } }
2095 if (dlopen_nodes[i].p == NULL) {
2096 unsigned int max = strlen(filename);
2097 if (max > sizeof(dlopen_nodes[i].path) - 1)
2098 max = sizeof(dlopen_nodes[i].path) - 1;
2099 memcpy(dlopen_nodes[i].path, filename, max);
2100 dlopen_nodes[i].path[max] = '\0';
2101 dlopen_nodes[i].p = ret;
2102 dlopen_nodes[i].count = 1;
2103 break;
2104 }
2332
2333 if (dlopen_nodes[i].p == NULL)
2334 if (first_free == DLOPEN_MAX_ENTRIES)
2335 first_free = i;
2336 }
2337 xlog(101, "%s: found=%u first_free=%u\n", __func__, found, first_free);
2338
2339 if ((found == 0) && (first_free != DLOPEN_MAX_ENTRIES)) {
2340 xlog(101, "%s: store path [%s] in pos %u\n",
2341 __func__, filename, first_free);
2342 unsigned int max = strlen(filename);
2343 if (max > sizeof(dlopen_nodes[first_free].path) - 1)
2344 max = sizeof(dlopen_nodes[first_free].path) - 1;
2345 memcpy(dlopen_nodes[first_free].path, filename, max);
2346 dlopen_nodes[first_free].path[max] = '\0';
2347 dlopen_nodes[first_free].p = ret;
2348 dlopen_nodes[first_free].count = 1;
2105 2349 } }
2106 2350 } }
2107 2351
2108 my_trace(__func__, 'r', filename, flags, ret);
2109
2110 2352 return ret; return ret;
2111 2353 } }
2112 2354
 
... ... int dlclose(void *h)
2114 2356 { {
2115 2357 int ret; int ret;
2116 2358
2117 //xlog(100, "%s(%p)\n", __func__, h);
2359 xlog(100, "%s(%p)\n", __func__, h);
2118 2360
2119 2361 if (!old_dlclose) if (!old_dlclose)
2120 2362 return 0; return 0;
 
... ... int dlclose(void *h)
2124 2366 for (unsigned i = 0; i < DLOPEN_MAX_ENTRIES; i++) { for (unsigned i = 0; i < DLOPEN_MAX_ENTRIES; i++) {
2125 2367 if (dlopen_nodes[i].p == h) { if (dlopen_nodes[i].p == h) {
2126 2368 dlopen_nodes[i].count--; dlopen_nodes[i].count--;
2127 if (dlopen_nodes[i].count == 0)
2369 if (dlopen_nodes[i].count == 0) {
2128 2370 dlopen_nodes[i].p = NULL; dlopen_nodes[i].p = NULL;
2371 xlog(100, "%s: freeing file [%s] on pos %u\n",
2372 __func__, dlopen_nodes[i].path, i);
2373 }
2129 2374 break; break;
2130 2375 } }
2131 2376 } }
2132 2377 } }
2133 2378
2134 my_trace(__func__, 'r', h, ret);
2379 my_trace(__func__, 'R', h, ret);
2135 2380
2136 2381 return ret; return ret;
2137 2382 } }
 
... ... void *ninedogs_dlsym(const char *sym)
2143 2388 { {
2144 2389 void *ret; void *ret;
2145 2390
2391 xlog(100, "%s: sym [%s]\n", __func__, sym);
2392
2146 2393 ret = old_dlsym(RTLD_NEXT, sym); ret = old_dlsym(RTLD_NEXT, sym);
2147 2394 if (ret) if (ret)
2148 2395 return ret; return ret;
2149 2396
2150 2397 for (unsigned i = 0; i < DLOPEN_MAX_ENTRIES; i++) { for (unsigned i = 0; i < DLOPEN_MAX_ENTRIES; i++) {
2398 if (!dlopen_nodes[i].p)
2399 continue;
2400
2151 2401 ret = old_dlsym(dlopen_nodes[i].p, sym); ret = old_dlsym(dlopen_nodes[i].p, sym);
2152 2402 if (ret) { if (ret) {
2153 xlog(0, "%s: sym [%s] found in [%s]\n",
2403 xlog(100, "%s: sym [%s] found in [%s]\n",
2154 2404 __func__, sym, dlopen_nodes[i].path); __func__, sym, dlopen_nodes[i].path);
2155 2405 return ret; return ret;
2156 2406 } }
 
... ... ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
2166 2416 if (!old_getrandom) if (!old_getrandom)
2167 2417 ninedogs_init(); ninedogs_init();
2168 2418
2169 xlog(20, "%s(%p, %zu, 0x%x) [old_getrandom=%p]\n",
2419 xlog(100, "%s(%p, %zu, 0x%x) [old_getrandom=%p]\n",
2170 2420 __func__, buf, buflen, flags, old_getrandom); __func__, buf, buflen, flags, old_getrandom);
2171 2421
2172 2422 my_trace(__func__, 'c', buflen, flags); my_trace(__func__, 'c', buflen, flags);
 
... ... int nanosleep(const struct timespec *req, struct timespec *rem)
2183 2433 if (!old_nanosleep) if (!old_nanosleep)
2184 2434 ninedogs_init(); ninedogs_init();
2185 2435
2186 xlog(20, "%s(%ld.%09ld, %p)\n",
2436 xlog(100, "%s(%ld.%09ld, %p)\n",
2187 2437 __func__, req->tv_sec, req->tv_nsec, rem); __func__, req->tv_sec, req->tv_nsec, rem);
2188 2438
2189 2439 my_trace(__func__, 'c', req); my_trace(__func__, 'c', req);
 
... ... int unlink(const char *pathname)
2200 2450 if (!old_unlink) if (!old_unlink)
2201 2451 ninedogs_init(); ninedogs_init();
2202 2452
2203 xlog(20, "%s(%s)\n", __func__, pathname);
2453 xlog(100, "%s(%s)\n", __func__, pathname);
2204 2454
2205 2455 my_trace(__func__, 'c', pathname); my_trace(__func__, 'c', pathname);
2206 2456 ret = old_unlink(pathname); ret = old_unlink(pathname);
 
... ... int listen(int sock, int backlog)
2216 2466 if (!old_listen) if (!old_listen)
2217 2467 ninedogs_init(); ninedogs_init();
2218 2468
2219 xlog(20, "%s(%d, %d)\n", __func__, sock, backlog);
2469 xlog(100, "%s(%d, %d)\n", __func__, sock, backlog);
2220 2470
2221 2471 ret = old_listen(sock, backlog); ret = old_listen(sock, backlog);
2222 my_trace(__func__, 'r', sock, backlog, ret);
2472 my_trace(__func__, 'R', sock, backlog, ret);
2223 2473
2224 2474 return ret; return ret;
2225 2475 } }
 
... ... void syslog(int priority, const char *format, ...)
2232 2482 if (!old_syslog) if (!old_syslog)
2233 2483 ninedogs_init(); ninedogs_init();
2234 2484
2235 xlog(20, "%s(%d)\n", __func__, priority);
2485 xlog(100, "%s(%d)\n", __func__, priority);
2236 2486
2237 2487 va_start(va, format); va_start(va, format);
2238 2488 vsnprintf(buf, sizeof(buf), format, va); vsnprintf(buf, sizeof(buf), format, va);
2239 2489 va_end(va); va_end(va);
2240 2490
2241 2491 old_syslog(priority, buf); old_syslog(priority, buf);
2242 my_trace(__func__, 'r', priority, buf);
2492 my_trace(__func__, 'R', priority, buf);
2243 2493 } }
2244 2494
2245 2495 int fstatat(int dirfd, const char *restrict pathname, int fstatat(int dirfd, const char *restrict pathname,
 
... ... int fstatat(int dirfd, const char *restrict pathname,
2250 2500 if (!old_fstatat) if (!old_fstatat)
2251 2501 ninedogs_init(); ninedogs_init();
2252 2502
2253 xlog(20, "%s(%d, %s, %p, 0x%x)\n", __func__, dirfd, pathname, statbuf, flags);
2503 xlog(100, "%s(%d, %s, %p, 0x%x)\n", __func__, dirfd, pathname, statbuf, flags);
2254 2504
2255 2505 my_trace(__func__, 'c', dirfd, pathname, flags); my_trace(__func__, 'c', dirfd, pathname, flags);
2256 2506 ret = old_fstatat(dirfd, pathname, statbuf, flags); ret = old_fstatat(dirfd, pathname, statbuf, flags);
 
... ... int fstatat64(int dirfd, const char *restrict pathname,
2267 2517 if (!old_fstatat64) if (!old_fstatat64)
2268 2518 ninedogs_init(); ninedogs_init();
2269 2519
2270 xlog(20, "%s(%d, %s, %p, 0x%x)\n",
2520 xlog(100, "%s(%d, %s, %p, 0x%x)\n",
2271 2521 __func__, dirfd, pathname, statbuf, flags); __func__, dirfd, pathname, statbuf, flags);
2272 2522
2273 2523 my_trace(__func__, 'c', dirfd, pathname, flags); my_trace(__func__, 'c', dirfd, pathname, flags);
 
... ... int fstatat64(int dirfd, const char *restrict pathname,
2277 2527 return ret; return ret;
2278 2528 } }
2279 2529
2280 int newfstatat(int dirfd, const char *restrict pathname,
2281 struct stat64 *restrict statbuf, int flags)
2530 int stat(const char *restrict pathname, struct stat *restrict statbuf)
2282 2531 { {
2283 2532 int ret; int ret;
2284 2533
2285 if (!old_fstatat64)
2534 if (!old_stat)
2286 2535 ninedogs_init(); ninedogs_init();
2287 2536
2288 xlog(20, "%s(%d, %s, %p, 0x%x)\n",
2289 __func__, dirfd, pathname, statbuf, flags);
2537 xlog(100, "%s(%s, %p)\n",
2538 __func__, pathname, statbuf);
2290 2539
2291 my_trace(__func__, 'c', dirfd, pathname, flags);
2292 ret = old_fstatat64(dirfd, pathname, statbuf, flags);
2293 my_trace(__func__, 'r', dirfd, pathname, statbuf, flags, ret);
2540 my_trace(__func__, 'c', pathname);
2541 ret = old_stat(pathname, statbuf);
2542 my_trace(__func__, 'r', pathname, statbuf, ret);
2294 2543
2295 2544 return ret; return ret;
2296 2545 } }
2297 2546
2298 int stat(const char *restrict pathname, struct stat *restrict statbuf)
2547 int fork(void)
2299 2548 { {
2300 2549 int ret; int ret;
2301 2550
2302 if (!old_stat)
2551 if (!old_fork)
2303 2552 ninedogs_init(); ninedogs_init();
2304 2553
2305 xlog(20, "%s(%s, %p)\n",
2306 __func__, pathname, statbuf);
2554 xlog(100, "%s()\n", __func__);
2307 2555
2308 my_trace(__func__, 'c', pathname);
2309 ret = old_stat(pathname, statbuf);
2310 my_trace(__func__, 'r', pathname, statbuf, ret);
2556 ret = old_fork();
2557 my_trace(__func__, 'R', ret);
2558
2559 return ret;
2560 }
2561
2562 static int (*old_sqlite3_open)(const char *, void **);
2563 int sqlite3_open(const char *filename, void **ppdb)
2564 {
2565 int ret;
2566
2567 if (!old_sqlite3_open)
2568 old_sqlite3_open = ninedogs_dlsym("sqlite3_open");
2569
2570 xlog(100, "%s(%s)\n", __func__, filename);
2571
2572 my_trace(__func__, 'c', filename);
2573 ret = old_sqlite3_open(filename, ppdb);
2574 my_trace(__func__, 'r', filename, ppdb, ret);
2575
2576 return ret;
2577 }
2578
2579 static int (*old_sqlite3_open_v2)(const char *, void **, int, const char *);
2580 int sqlite3_open_v2(const char *filename, void **ppdb, int flags, const char *vfs)
2581 {
2582 int ret;
2583
2584 if (!old_sqlite3_open_v2)
2585 old_sqlite3_open_v2 = ninedogs_dlsym("sqlite3_open_v2");
2586
2587 xlog(100, "%s(%s, ppdb, 0x%x, %s)\n",
2588 __func__, filename, flags, vfs);
2589
2590 my_trace(__func__, 'c', filename, flags, vfs);
2591 ret = old_sqlite3_open_v2(filename, ppdb, flags, vfs);
2592 my_trace(__func__, 'r', filename, ppdb ? *ppdb : NULL, flags, vfs, ret);
2311 2593
2312 2594 return ret; return ret;
2313 2595 } }
2596
2597 static int (*old_sqlite3_open16)(const char *, void **);
2598 int sqlite3_open16(const char *filename, void **ppdb)
2599 {
2600 int ret;
2601
2602 if (!old_sqlite3_open16)
2603 old_sqlite3_open16 = ninedogs_dlsym("sqlite3_open16");
2604
2605 xlog(100, "%s('%s', ppdb)\n",
2606 __func__, filename);
2607
2608 my_trace(__func__, 'c', filename);
2609 ret = old_sqlite3_open16(filename, ppdb);
2610 my_trace(__func__, 'r', filename, ppdb, ret);
2611
2612 return ret;
2613 }
2614
2615 // TODO: this seems to be only a wrapper
2616 static int (*old_sqlite3_exec)(void *h, const char *sql,
2617 int (*callback)(void *, int, char **, char **), void *, char **errmsg);
2618 int sqlite3_exec(void *h, const char *sql,
2619 int (*callback)(void *, int, char **, char **), void *callback_arg, char **errmsg)
2620 {
2621 int ret;
2622
2623 if (!old_sqlite3_exec)
2624 old_sqlite3_exec = ninedogs_dlsym("sqlite3_exec");
2625
2626 //my_trace(__func__, 'c', h, sql, callback, callback_arg);
2627 ret = old_sqlite3_exec(h, sql, callback, callback_arg, errmsg);
2628 xlog(100, "%s(h=%p, sql='%s', cb=%p, cba=%p, err='%s')\n",
2629 __func__, h, sql, callback, callback_arg, errmsg ? *errmsg : "?");
2630 //my_trace(__func__, 'r', h, sql, callback, callback_arg, errmsg);
2631
2632 return ret;
2633 }
2634
2635 static int (*old_sqlite3_prepare_v2)(void *, const char *, int, void **, const char **);
2636 int sqlite3_prepare_v2(void *h, const char *sql, int nByte, void **stmt, const char **tail)
2637 {
2638 int ret;
2639
2640 if (!old_sqlite3_prepare_v2)
2641 old_sqlite3_prepare_v2 = ninedogs_dlsym("sqlite3_prepare_v2");
2642
2643 my_trace(__func__, 'c', h, sql, nByte);
2644 ret = old_sqlite3_prepare_v2(h, sql, nByte, stmt, tail);
2645 xlog(100, "%s(h=%p, sql='%s', nByte=%d, *stmt=%p, tail=[%s]) = %d\n",
2646 __func__, h, sql, nByte, stmt ? *stmt : NULL, tail ? *tail : "", ret);
2647 my_trace(__func__, 'r', h, sql, nByte, stmt ? *stmt : NULL, ret);
2648 // TODO: do we need 'tail'?
2649
2650 return ret;
2651 }
2652
2653 static int (*old_sqlite3_step)(void *);
2654 int sqlite3_step(void *stmt)
2655 {
2656 int ret;
2657
2658 if (!old_sqlite3_step)
2659 old_sqlite3_step = ninedogs_dlsym("sqlite3_step");
2660
2661 my_trace(__func__, 'c', stmt);
2662 ret = old_sqlite3_step(stmt);
2663 xlog(100, "%s(stmt=%p) = %d\n", __func__, stmt, ret);
2664 my_trace(__func__, 'r', stmt, ret);
2665
2666 return ret;
2667 }
2668
File agent/ninedogs.h changed (mode: 100644) (index 06aefde..58b0edd)
1 1 void ninedogs_fini(void); void ninedogs_fini(void);
2 2 void ninedogs_init(void); void ninedogs_init(void);
3 void my_trace(const char *func, const char type, ...);
3 4 void *ninedogs_dlsym(const char *sym); void *ninedogs_dlsym(const char *sym);
4 5
File agent/php.c changed (mode: 100644) (index 5e656a4..94e2548)
... ... struct zend_module_entry
68 68 unsigned char pad2[6]; unsigned char pad2[6];
69 69 void *ini_entry; void *ini_entry;
70 70 void *deps; void *deps;
71 char *name;
71 const char *name;
72 72 struct zend_function_entry *functions; struct zend_function_entry *functions;
73 73 void *junk[5]; void *junk[5];
74 74 const char *version; const char *version;
75 75 size_t globals_size; size_t globals_size;
76 void *globals;
77 void *globals_ctor;
78 void *globals_dtor;
79 void *post_deactivate_func;
80 int module_started;
81 unsigned char type;
82 unsigned char pad3[3];
83 void *handle;
84 int module_number;
85 int pad4;
86 const char *build_id;
76 87 }; };
77 88
78 89 typedef long zend_long; typedef long zend_long;
 
... ... struct zend_array
111 122 unsigned char nIteratorsCount; unsigned char nIteratorsCount;
112 123 unsigned char _unused2; unsigned char _unused2;
113 124 } v; } v;
114 unsigned int flags;
125 unsigned int flags;
115 126 } u; } u;
116 127 unsigned int nTableMask; unsigned int nTableMask;
117 struct Bucket *arData;
128 union {
129 uint32_t *arHash;
130 struct Bucket *arData;
131 struct zval *arPacked;
132 };
118 133 unsigned int nNumUsed; unsigned int nNumUsed;
119 134 unsigned int nNumOfElements; unsigned int nNumOfElements;
120 135 unsigned int nTableSize; unsigned int nTableSize;
 
... ... struct Bucket
166 181
167 182 struct zend_reference struct zend_reference
168 183 { {
169 unsigned int refcount;
170 unsigned int pad1;
171 struct zval val;
172 /* more thigs follows */
184 struct zend_refcounted_h gc;
185 struct zval val;
186 void *sources;
173 187 }; };
174 188
175 189 struct zend_execute_data struct zend_execute_data
 
... ... static void php_zed_dump(const char *prefix, struct zend_execute_data *p)
305 319 } }
306 320 } }
307 321
322 static void zend_array_to_params_array(struct query *q, struct zend_array *za)
323 {
324 unsigned int i = 0, max;
325
326 xlog(100, " nTableMask=0x%x nNumUsed=%u nNumOfElements=%u nTableSize=%u"
327 " nInternalPointer=%u flags=0x%x[%s]\n",
328 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize,
329 za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : "");
330
331 max = za->nNumUsed;
332 if (max > ND_PARAMS_MAX)
333 max = ND_PARAMS_MAX;
334
335 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
336 for (; bs != be; bs++) {
337 struct zval *_z = &bs->val;
338
339 if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT
340 _z = _z->value.zv;
341
342 if (_z->u1.v.type == 0 /*IS_UNDEF*/) {
343 xlog(101, " para h=%lu: type undef\n", bs->h);
344 continue;
345 }
346
347 if (_z->u1.v.type == 10) { // REFERENCE
348 xlog(101, " is a reference!\n");
349 _z = &_z->value.ref->val;
350 }
351
352 struct zend_string *zs = bs->key;
353 xlog(101, " para: bs=%p h=%lu key=[%p] type %s: val: %s\n",
354 bs, bs->h, zs, php_get_type(_z), php_get_value(_z));
355
356 if (_z->u1.v.type == 4) {
357 q->params[i].type = ND_PARAMS_TYPE_LONG;
358 q->params[i].l = _z->value.lval;
359 } else if (_z->u1.v.type == 5) {
360 q->params[i].type = ND_PARAMS_TYPE_DOUBLE;
361 q->params[i].d = _z->value.dval;
362 } else if (_z->u1.v.type == 6) {
363 q->params[i].type = ND_PARAMS_TYPE_STRING;
364 struct zend_string *zs = _z->value.str;
365 q->params[i].str = zs->val;
366 q->params[i].length = zs->len;
367 }
368
369 i++;
370 if (i == max)
371 break;
372 }
373
374 q->params_len = za->nNumUsed;
375 }
376
308 377 void *(*old_pg_last_error)(struct zend_execute_data *, struct zval *); void *(*old_pg_last_error)(struct zend_execute_data *, struct zval *);
309 378 static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv) static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv)
310 379 { {
 
... ... static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv)
324 393 return ret; return ret;
325 394 } }
326 395
396 void *(*old_pg_close)(struct zend_execute_data *, struct zval *);
397 static void *my_pg_close(struct zend_execute_data *e, struct zval *retv)
398 {
399 void *ret;
400 unsigned int num_args, s;
401 struct zval *z;
402 struct conn cs;
403
404 num_args = e->This.u2.num_args;
405 //xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
406
407 cs.type = 'P';
408 if (num_args == 1) {
409 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
410 // handler, may be null
411 z = (struct zval *) e + s; s++;
412 cs.dbh = z->value.p;
413 //xlog(101, " h=%p\n", cs.dbh);
414 } else {
415 cs.dbh = NULL;
416 }
417
418 ret = old_pg_close(e, retv);
419 ninedogs_process_db("pg_close", NINEDOGS_DB_CONN_CLOSE, &cs);
420
421 return ret;
422 }
423
327 424 void *(*old_pg_connect)(struct zend_execute_data *, struct zval *); void *(*old_pg_connect)(struct zend_execute_data *, struct zval *);
328 425 static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv) static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv)
329 426 { {
 
... ... static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv)
334 431 struct conn cs; struct conn cs;
335 432
336 433 num_args = e->This.u2.num_args; num_args = e->This.u2.num_args;
337 xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
434 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
338 435
339 436 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);
340 437 cs.type = 'P'; cs.type = 'P';
 
... ... static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv)
344 441 q = z->value.str; q = z->value.str;
345 442 cs.conn_str = q->val; cs.conn_str = q->val;
346 443 cs.conn_str_len = q->len; cs.conn_str_len = q->len;
347 xlog(50, " conn: %s\n", cs.conn_str);
444 //xlog(50, " conn[%u]: %s\n", cs.conn_str_len, cs.conn_str);
348 445
349 ninedogs_now(&cs.start);
446 ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_START, &cs);
350 447 ret = old_pg_connect(e, retv); ret = old_pg_connect(e, retv);
351 if (!retv)
448 if (!retv) {
449 xlog(0, "DEBUG: old_pg_connect returned retv NULL\n");
352 450 return ret; return ret;
353 ninedogs_now(&cs.end);
451 }
354 452
355 //php_zval_dump(" retv: ", retv);
453 php_zval_dump(" retv: ", retv);
356 454 // TODO: how to test for error? if (core_globals.last_error_message) { // TODO: how to test for error? if (core_globals.last_error_message) {
357 455
358 456 // PHP7 returns resource, PHP8.1 returns object // PHP7 returns resource, PHP8.1 returns object
359 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) {
457 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9))
360 458 cs.dbh = retv->value.p; cs.dbh = retv->value.p;
361 ninedogs_process_db(NINEDOGS_DB_CONN, &cs);
362 }
459 else
460 cs.dbh = NULL;
461 ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_END, &cs);
363 462
364 463 return ret; return ret;
365 464 } }
 
... ... static void *my_pg_pconnect(struct zend_execute_data *e, struct zval *retv)
386 485 cs.conn_str_len = q->len; cs.conn_str_len = q->len;
387 486 xlog(50, " conn: %s\n", cs.conn_str); xlog(50, " conn: %s\n", cs.conn_str);
388 487
389 ninedogs_now(&cs.start);
488 ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_START, &cs);
390 489 ret = old_pg_pconnect(e, retv); ret = old_pg_pconnect(e, retv);
391 490 if (!retv) if (!retv)
392 491 return ret; return ret;
393 ninedogs_now(&cs.end);
394 492
395 //php_zval_dump(" retv: ", retv);
493 php_zval_dump(" retv: ", retv);
396 494 // TODO: how to test for error? if (core_globals.last_error_message) { // TODO: how to test for error? if (core_globals.last_error_message) {
397 495
398 496 // PHP7 returns resource, PHP8.1 returns object // PHP7 returns resource, PHP8.1 returns object
399 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) {
497 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9))
400 498 cs.dbh = retv->value.p; cs.dbh = retv->value.p;
401 ninedogs_process_db(NINEDOGS_DB_CONN, &cs);
402 }
499 else
500 cs.dbh = NULL;
501 ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_END, &cs);
403 502
404 503 return ret; return ret;
405 504 } }
 
... ... static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv)
414 513 struct free_result fr; struct free_result fr;
415 514
416 515 unsigned int num_args = e->This.u2.num_args; unsigned int num_args = e->This.u2.num_args;
417 xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
516 xlog(200, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
418 517 //php_zed_dump(" e: ", e); //php_zed_dump(" e: ", e);
419 518 //php_zval_dump(" retv: ", retv); //php_zval_dump(" retv: ", retv);
420 519
 
... ... static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv)
434 533 fr.ok = 0; fr.ok = 0;
435 534 } }
436 535
437 ninedogs_process_db(NINEDOGS_DB_FREE_RESULT, &fr);
536 ninedogs_process_db("pg_free_result", NINEDOGS_DB_FREE_RESULT, &fr);
438 537
439 538 return ret; return ret;
440 539 } }
 
... ... static void php_set_para(struct zend_execute_data *e, const unsigned int i,
469 568 memcpy(dst, para, sizeof(struct zval)); memcpy(dst, para, sizeof(struct zval));
470 569 } }
471 570
472 static void php_set_last_error(struct zend_execute_data *e,
571 static void php_pg_set_last_error(struct zend_execute_data *e,
473 572 struct zval *dbh, struct query *q) struct zval *dbh, struct query *q)
474 573 { {
475 574 struct zval rz; struct zval rz;
 
... ... static void php_set_last_error(struct zend_execute_data *e,
494 593 } }
495 594 } }
496 595
497 static void php_set_num_aff(struct zend_execute_data *e, struct zval *res,
596 static void php_pg_set_num_aff(struct zend_execute_data *e, struct zval *res,
498 597 struct query *q) struct query *q)
499 598 { {
500 599 struct zval rz; struct zval rz;
 
... ... static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
533 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);
534 633 para = (struct zval *) e + s; para = (struct zval *) e + s;
535 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;
536 636
537 637 if (num_args == 2) { if (num_args == 2) {
538 638 // link // link
 
... ... static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
550 650 qs.q = q->val; qs.q = q->val;
551 651 qs.q_len = q->len; qs.q_len = q->len;
552 652
553 ninedogs_now(&qs.start);
653 ninedogs_process_db("pg_query", NINEDOGS_DB_QUERY_START, &qs);
554 654 ret = old_pg_query(e, retv); ret = old_pg_query(e, retv);
555 655 if (!retv) if (!retv)
556 656 return ret; return ret;
557 ninedogs_now(&qs.end);
558 657
559 658 xlog(100, " old %s returned type=%s value=%s\n", xlog(100, " old %s returned type=%s value=%s\n",
560 659 __func__, php_get_type(retv), php_get_value(retv)); __func__, php_get_type(retv), php_get_value(retv));
 
... ... static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
563 662 memcpy(&copy_para, para, sizeof(struct zval)); memcpy(&copy_para, para, sizeof(struct zval));
564 663
565 664 if (retv->u1.v.type == 2) { // false if (retv->u1.v.type == 2) { // false
566 php_set_last_error(e, dbh, &qs);
665 php_pg_set_last_error(e, dbh, &qs); // TODO is qs.res set here?
567 666 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
568 qs.res = retv->value.str;
569 php_set_num_aff(e, retv, &qs);
667 qs.res = retv->value.p;
668 php_pg_set_num_aff(e, retv, &qs);
570 669 do_restore = 1; do_restore = 1;
571 670 } }
572 671
 
... ... static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
574 673 if (do_restore) if (do_restore)
575 674 memcpy(para, &copy_para, sizeof(struct zval)); memcpy(para, &copy_para, sizeof(struct zval));
576 675
577 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
676 ninedogs_process_db("pg_query", NINEDOGS_DB_QUERY_END, &qs);
578 677
579 678 return ret; return ret;
580 679 } }
 
... ... static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv)
593 692
594 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);
595 694 qs.type = 'P'; qs.type = 'P';
695 qs.params_len = 0;
596 696
597 697 // link // link
598 698 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
 
... ... static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv)
606 706 qs.q_len = q->len; qs.q_len = q->len;
607 707 xlog(100, " query=%s\n", qs.q); xlog(100, " query=%s\n", qs.q);
608 708
609 ninedogs_now(&qs.start);
709 ninedogs_process_db("pg_send_query", NINEDOGS_DB_QUERY_START, &qs);
610 710 ret = old_pg_send_query(e, retv); ret = old_pg_send_query(e, retv);
611 711 if (!retv) if (!retv)
612 712 return ret; return ret;
613 ninedogs_now(&qs.end);
614 713
615 xlog(1, " old %s returned type=%s value=%s\n",
714 xlog(101, " old %s returned type=%s value=%s\n",
616 715 __func__, php_get_type(retv), php_get_value(retv)); __func__, php_get_type(retv), php_get_value(retv));
617 716
618 717 qs.res = NULL; qs.res = NULL;
619 718 if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int
620 php_set_last_error(e, dbh, &qs);
719 php_pg_set_last_error(e, dbh, &qs);
621 720 } else if (retv->u1.v.type == 3) { // true = success } else if (retv->u1.v.type == 3) { // true = success
622 721 qs.num = qs.aff = 0; qs.num = qs.aff = 0;
722 qs.res = (void *) 1; // signal ok
623 723 } }
624 724
625 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
725 ninedogs_process_db("pg_send_query", NINEDOGS_DB_QUERY_END, &qs);
626 726
627 727 return ret; return ret;
628 728 } }
 
... ... static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv)
644 744 para = (struct zval *) e + s; para = (struct zval *) e + s;
645 745 qs.type = 'P'; qs.type = 'P';
646 746 qs.q = NULL; qs.q = NULL;
747 qs.params_len = 0;
647 748
648 749 // link // link
649 750 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
650 751 //php_zval_dump(" dbh: ", z); //php_zval_dump(" dbh: ", z);
651 752 qs.dbh = z->value.p; qs.dbh = z->value.p;
652 753
653 ninedogs_now(&qs.start);
754 ninedogs_process_db("pg_get_result", NINEDOGS_DB_QUERY_START, &qs);
654 755 ret = old_pg_get_result(e, retv); ret = old_pg_get_result(e, retv);
655 756 if (!retv) if (!retv)
656 757 return ret; return ret;
657 ninedogs_now(&qs.end);
658 758
659 759 xlog(100, " old %s returned type=%s value=%s\n", xlog(100, " old %s returned type=%s value=%s\n",
660 760 __func__, php_get_type(retv), php_get_value(retv)); __func__, php_get_type(retv), php_get_value(retv));
 
... ... static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv)
663 763 memcpy(&copy_para, para, sizeof(struct zval)); memcpy(&copy_para, para, sizeof(struct zval));
664 764
665 765 if (retv->u1.v.type == 2) { // false if (retv->u1.v.type == 2) { // false
666 php_set_last_error(e, dbh, &qs);
766 php_pg_set_last_error(e, dbh, &qs);
667 767 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
668 768 qs.err = NULL; qs.err = NULL;
669 qs.res = retv->value.str;
670 php_set_num_aff(e, retv, &qs);
769 qs.res = retv->value.p;
770 php_pg_set_num_aff(e, retv, &qs);
671 771 do_restore = 1; do_restore = 1;
672 772 } }
673 773
 
... ... static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv)
675 775 if (do_restore) if (do_restore)
676 776 memcpy(para, &copy_para, sizeof(struct zval)); memcpy(para, &copy_para, sizeof(struct zval));
677 777
678 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
778 ninedogs_process_db("pg_get_result", NINEDOGS_DB_QUERY_END, &qs);
679 779
680 780 return ret; return ret;
681 781 } }
 
... ... static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv)
693 793 struct query qs; struct query qs;
694 794
695 795 num_args = e->This.u2.num_args; num_args = e->This.u2.num_args;
696 //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
796 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
697 797 //php_zed_dump(" e0: ", e); //php_zed_dump(" e0: ", e);
698 798 //php_zval_dump(" retv0: ", retv); //php_zval_dump(" retv0: ", retv);
699 799
 
... ... static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv)
717 817
718 818 // params (array) // params (array)
719 819 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
720 #if 1
721 struct zend_array *za;
722 za = z->value.arr;
723 xlog(200, " nTableMask=%u nNumUsed=%u nNumOfElements=%u nTableSize=%u nInternalPointer=%u\n",
724 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, za->nInternalPointer);
820 struct zend_array *za = z->value.arr;
821 zend_array_to_params_array(&qs, za);
725 822
726 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
727 unsigned int i = 1;
728 for (; bs != be; bs++) {
729 struct zval *_z = &bs->val;
730
731 if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT
732 _z = _z->value.zv;
733
734 if (_z->u1.v.type == 0 /*IS_UNDEF*/) continue;
735
736 if (_z->u1.v.type == 10) { // REFERENCE
737 xlog(1, " is a reference!\n");
738 _z = &_z->value.ref->val;
739 }
740
741 xlog(200, " para %u: type %s: val: %s\n",
742 i, php_get_type(_z), php_get_value(_z));
743 i++;
744 }
745 #endif
746
747 ninedogs_now(&qs.start);
823 ninedogs_process_db("pg_query_params", NINEDOGS_DB_QUERY_START, &qs);
748 824 ret = old_pg_query_params(e, retv); ret = old_pg_query_params(e, retv);
749 ninedogs_now(&qs.end);
750 825 //xlog(200, " old %s: type=%s value=%s\n", //xlog(200, " old %s: type=%s value=%s\n",
751 826 // __func__, php_get_type(retv), php_get_value(retv)); // __func__, php_get_type(retv), php_get_value(retv));
752 827 //php_zed_dump(" e1: ", e); //php_zed_dump(" e1: ", e);
753 //php_zval_dump(" retv1 after calling old func: ", retv);
828 //php_zval_dump(" retv after calling old func: ", retv);
754 829
755 830 copy_num_args = e->This.u2.num_args; copy_num_args = e->This.u2.num_args;
756 831 memcpy(&copy_para, para, sizeof(struct zval)); memcpy(&copy_para, para, sizeof(struct zval));
757 832
758 833 if (retv->u1.v.type == 2) { // false if (retv->u1.v.type == 2) { // false
759 php_set_last_error(e, dbh, &qs);
834 php_pg_set_last_error(e, dbh, &qs);
760 835 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
761 qs.res = retv->value.str;
762 php_set_num_aff(e, retv, &qs);
836 qs.res = retv->value.p;
837 php_pg_set_num_aff(e, retv, &qs);
763 838 do_restore = 1; do_restore = 1;
764 839 } }
765 840
 
... ... static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv)
769 844 if (do_restore) if (do_restore)
770 845 memcpy(para, &copy_para, sizeof(struct zval)); memcpy(para, &copy_para, sizeof(struct zval));
771 846
772 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
847 ninedogs_process_db("pg_query_params", NINEDOGS_DB_QUERY_END, &qs);
773 848
774 849 return ret; return ret;
775 850 } }
 
... ... static void *my_pg_send_query_params(struct zend_execute_data *e, struct zval *r
784 859 struct zend_string *q; struct zend_string *q;
785 860 struct query qs; struct query qs;
786 861
787 //unsigned int num_args = e->This.u2.num_args;
788 //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
862 unsigned int num_args = e->This.u2.num_args;
863 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
789 864 //php_zed_dump(" e0: ", e); //php_zed_dump(" e0: ", e);
790 865 //php_zval_dump(" retv0: ", retv); //php_zval_dump(" retv0: ", retv);
791 866
 
... ... static void *my_pg_send_query_params(struct zend_execute_data *e, struct zval *r
804 879
805 880 // params (array) // params (array)
806 881 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
807 #if 1
808 struct zend_array *za;
809 za = z->value.arr;
810 xlog(200, " nTableMask=%u nNumUsed=%u nNumOfElements=%u nTableSize=%u nInternalPointer=%u\n",
811 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, za->nInternalPointer);
882 struct zend_array *za = z->value.arr;
883 zend_array_to_params_array(&qs, za);
812 884
813 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
814 unsigned int i = 1;
815 for (; bs != be; bs++) {
816 struct zval *_z = &bs->val;
817
818 if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT
819 _z = _z->value.zv;
820
821 if (_z->u1.v.type == 0 /*IS_UNDEF*/) continue;
822
823 if (_z->u1.v.type == 10) { // REFERENCE
824 xlog(1, " is a reference!\n");
825 _z = &_z->value.ref->val;
826 }
827
828 xlog(200, " para %u: type %s: val: %s\n",
829 i, php_get_type(_z), php_get_value(_z));
830 i++;
831 }
832 #endif
833
834 ninedogs_now(&qs.start);
885 ninedogs_process_db("pg_send_query_params", NINEDOGS_DB_QUERY_START, &qs);
835 886 ret = old_pg_send_query_params(e, retv); ret = old_pg_send_query_params(e, retv);
836 ninedogs_now(&qs.end);
837 887 //xlog(200, " old %s: type=%s value=%s\n", //xlog(200, " old %s: type=%s value=%s\n",
838 888 // __func__, php_get_type(retv), php_get_value(retv)); // __func__, php_get_type(retv), php_get_value(retv));
839 889 //php_zed_dump(" e1: ", e); //php_zed_dump(" e1: ", e);
840 //php_zval_dump(" retv1 after calling old func: ", retv);
890 //php_zval_dump(" retv after calling old func: ", retv);
841 891
842 892 qs.res = NULL; qs.res = NULL;
843 893 if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int (probably 0) if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int (probably 0)
844 php_set_last_error(e, dbh, &qs);
894 php_pg_set_last_error(e, dbh, &qs);
845 895 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
846 896 qs.num = qs.aff = 0; qs.num = qs.aff = 0;
897 qs.res = (void *) 1; // signal ok
898 }
899
900 ninedogs_process_db("pg_send_query_params", NINEDOGS_DB_QUERY_END, &qs);
901
902 return ret;
903 }
904
905
906 void *(*old_mysqli_connect)(struct zend_execute_data *, struct zval *);
907 static void *my_mysqli_connect(struct zend_execute_data *e, struct zval *retv)
908 {
909 void *ret;
910 unsigned int num_args, s;
911 struct zval *z;
912 struct conn cs;
913 char *host = "", *user = "", *db = "", *sock = "";
914 int port = 0;
915
916 num_args = e->This.u2.num_args;
917 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
918
919 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
920 cs.type = 'M';
921
922 if (num_args >= 1) { // host
923 z = (struct zval *) e + s; s++;
924 php_zval_dump(" host: ", z);
925 if (z->u1.v.type == 6) // string
926 host = z->value.str->val;
927 }
928
929 if (num_args >= 2) { // user
930 z = (struct zval *) e + s; s++;
931 if (z->u1.v.type == 6) // string
932 user = z->value.str->val;
933 }
934
935 if (num_args >= 3) // pass
936 s++;
937
938 if (num_args >= 4) { // db
939 z = (struct zval *) e + s; s++;
940 if (z->u1.v.type == 6) // string
941 db = z->value.str->val;
942 }
943
944 if (num_args >= 5) { // port
945 z = (struct zval *) e + s; s++;
946 if (z->u1.v.type == 4) // long
947 port = z->value.lval;
948 }
949
950 if (num_args >= 6) { // socket
951 z = (struct zval *) e + s; s++;
952 if (z->u1.v.type == 6) // string
953 sock = z->value.str->val;
954 }
955
956 char conn_str[512];
957 snprintf(conn_str, sizeof(conn_str),
958 "host=%s user=%s port=%d db=%s socket=%s",
959 host, user, port, db, sock);
960 cs.conn_str = conn_str;
961 cs.conn_str_len = strlen(cs.conn_str);
962
963 ninedogs_process_db("mysqli_connect", NINEDOGS_DB_CONN_START, &cs);
964 ret = old_mysqli_connect(e, retv);
965 if (!retv) {
966 xlog(1, "DEBUG: old_mysqli_connect returned retv NULL\n");
967 return ret;
968 }
969 //php_zval_dump(" retv: ", retv);
970 // TODO: how to test for error? if (core_globals.last_error_message) {
971
972 // PHP7 returns resource, PHP8.1 returns object
973 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9))
974 cs.dbh = retv->value.p;
975 else
976 cs.dbh = NULL;
977 ninedogs_process_db("mysqli_connect", NINEDOGS_DB_CONN_END, &cs);
978
979 return ret;
980 }
981
982 void *(*old_mysqli_real_connect)(struct zend_execute_data *, struct zval *);
983 static void *my_mysqli_real_connect(struct zend_execute_data *e, struct zval *retv)
984 {
985 void *ret;
986 unsigned int num_args, s;
987 struct zval *z;
988 struct conn cs;
989 char *host = "", *user = "", *db = "", *sock = "";
990 int port = 0;
991
992 num_args = e->This.u2.num_args;
993 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
994
995 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
996 cs.type = 'M';
997 cs.flags = 0;
998
999 if (num_args >= 1) { // dbh
1000 z = (struct zval *) e + s; s++;
1001 if ((z->u1.v.type == 8) || (z->u1.v.type == 9)) // object or resource
1002 cs.dbh = z->value.p;
1003 }
1004
1005 if (num_args >= 2) { // host
1006 z = (struct zval *) e + s; s++;
1007 php_zval_dump(" host: ", z);
1008 if (z->u1.v.type == 6) // string
1009 host = z->value.str->val;
1010 }
1011
1012 if (num_args >= 3) { // user
1013 z = (struct zval *) e + s; s++;
1014 if (z->u1.v.type == 6) // string
1015 user = z->value.str->val;
1016 }
1017
1018 if (num_args >= 4) // pass
1019 s++;
1020
1021 if (num_args >= 5) { // db
1022 z = (struct zval *) e + s; s++;
1023 if (z->u1.v.type == 6) // string
1024 db = z->value.str->val;
1025 }
1026
1027 if (num_args >= 6) { // port
1028 z = (struct zval *) e + s; s++;
1029 if (z->u1.v.type == 4) // long
1030 port = z->value.lval;
1031 }
1032
1033 if (num_args >= 7) { // socket
1034 z = (struct zval *) e + s; s++;
1035 if (z->u1.v.type == 6) // string
1036 sock = z->value.str->val;
1037 }
1038
1039 if (num_args >= 8) { // flags
1040 z = (struct zval *) e + s; s++;
1041 if (z->u1.v.type == 4) // long
1042 cs.flags = z->value.lval;
1043 }
1044
1045 char conn_str[512];
1046 snprintf(conn_str, sizeof(conn_str),
1047 "host=%s user=%s port=%d db=%s socket=%s",
1048 host, user, port, db, sock);
1049 cs.conn_str = conn_str;
1050 cs.conn_str_len = strlen(cs.conn_str);
1051
1052 ninedogs_process_db("mysqli_real_connect", NINEDOGS_DB_CONN_START, &cs);
1053 ret = old_mysqli_real_connect(e, retv);
1054 if (!retv) {
1055 xlog(1, "DEBUG: old_mysqli_real_connect returned retv NULL\n");
1056 return ret;
1057 }
1058 //php_zval_dump(" retv: ", retv);
1059 // TODO: how to test for error? if (core_globals.last_error_message) {
1060
1061 // PHP7 returns resource, PHP8.1 returns object
1062 if (retv->u1.v.type == 3)
1063 cs.ret = 1;
1064 else
1065 cs.ret = 0;
1066 ninedogs_process_db("mysqli_real_connect", NINEDOGS_DB_CONN_END, &cs);
1067
1068 return ret;
1069 }
1070
1071 void *(*old_mysqli_query)(struct zend_execute_data *, struct zval *);
1072 static void *my_mysqli_query(struct zend_execute_data *e, struct zval *retv)
1073 {
1074 void *ret;
1075 unsigned int num_args, copy_num_args, s;
1076 struct zend_string *q;
1077 struct zval *z, copy_para, *para;
1078 char do_restore = 0;
1079 struct query qs;
1080
1081 num_args = e->This.u2.num_args;
1082
1083 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1084
1085 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1086 para = (struct zval *) e + s;
1087 qs.type = 'M';
1088 qs.params_len = 0;
1089
1090 // link
1091 z = (struct zval *) e + s; s++;
1092 php_zval_dump(" dbh: ", z);
1093 qs.dbh = z->value.p;
1094
1095 // query
1096 z = (struct zval *) e + s; s++;
1097 q = z->value.str;
1098 xlog(50, " query=%s\n", q->val);
1099 qs.q = q->val;
1100 qs.q_len = q->len;
1101
1102 // mode
1103 if (num_args >= 3) {
1104 z = (struct zval *) e + s; s++;
1105 xlog(50, " mode=0x%lx\n", z->value.lval);
1106 }
1107
1108 ninedogs_process_db("mysqli_query", NINEDOGS_DB_QUERY_START, &qs);
1109 ret = old_mysqli_query(e, retv);
1110 if (!retv)
1111 return ret;
1112 php_zval_dump(" retv: ", retv);
1113
1114 copy_num_args = num_args;
1115 memcpy(&copy_para, para, sizeof(struct zval));
1116
1117 if (retv->u1.v.type == 2) { // false
1118 // TODO php_mysqli_set_last_error(e, dbh, &qs); // TODO is qs.res set here?
1119 // TODO: do we set num and aff?
1120 qs.res = (void *) 0;
1121 } else if (retv->u1.v.type == 3) { // true (for queries not returning rows)
1122 qs.num = qs.aff = 0;
1123 qs.res = (void *) 1;
1124 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
1125 qs.res = retv->value.p;
1126 //TODO php_mysqli_set_num_aff(e, retv, &qs);
1127 do_restore = 1;
1128 }
1129
1130 e->This.u2.num_args = copy_num_args;
1131 if (do_restore)
1132 memcpy(para, &copy_para, sizeof(struct zval));
1133
1134 ninedogs_process_db("mysqli_query", NINEDOGS_DB_QUERY_END, &qs);
1135
1136 return ret;
1137 }
1138
1139 void *(*old_mysqli_close)(struct zend_execute_data *, struct zval *);
1140 static void *my_mysqli_close(struct zend_execute_data *e, struct zval *retv)
1141 {
1142 struct conn c;
1143
1144 unsigned int num_args = e->This.u2.num_args;
1145
1146 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1147
1148 unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
1149 struct zval *para = (struct zval *) e + s;
1150 c.type = 'M';
1151
1152 // link
1153 struct zval *z = (struct zval *) e + s; s++;
1154 php_zval_dump(" dbh: ", z);
1155 c.dbh = z->value.p;
1156
1157 void *ret = old_mysqli_close(e, retv);
1158 if (!retv)
1159 return ret;
1160 php_zval_dump(" retv: ", retv);
1161
1162 if (retv->u1.v.type == 2) { // false
1163 c.ret = 0;
1164 // TODO php_mysqli_set_last_error(e, dbh, &qs); // TODO is qs.res set here?
1165 // TODO: do we set num and aff?
1166 } else if (retv->u1.v.type == 3) { // true (for queries not returning rows)
1167 c.ret = 1;
847 1168 } }
848 1169
849 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
1170 ninedogs_process_db("mysqli_close", NINEDOGS_DB_CONN_CLOSE, &c);
850 1171
851 1172 return ret; return ret;
852 1173 } }
853 1174
1175
854 1176 struct zend_module_entry *(*old_get_module)(void); struct zend_module_entry *(*old_get_module)(void);
855 1177 static struct zend_module_entry *php_hook_get_module_func(void) static struct zend_module_entry *php_hook_get_module_func(void)
856 1178 { {
 
... ... static struct zend_module_entry *php_hook_get_module_func(void)
859 1181 unsigned int count; unsigned int count;
860 1182
861 1183 z = old_get_module(); z = old_get_module();
1184 xlog(100, " %s: calling old_get_module returned %p\n", __func__, z);
862 1185 if (!z) if (!z)
863 1186 return NULL; return NULL;
864 1187
865 if (strcmp(z->name, "pgsql") != 0)
1188 xlog(100, " %s: name=[%s] size=%hu zend_api=%u zts=%hhu version=[%s] functions=%p"
1189 " build_id=[%s]\n",
1190 __func__, z->name, z->size, z->zend_api, z->zts, z->version, z->functions,
1191 z->build_id);
1192
1193 if (sizeof(struct zend_module_entry) != z->size) {
1194 xlog(1, "%s: sizeof(struct zend_module_entry)[%zu] is not %hu!\n",
1195 sizeof(struct zend_module_entry), z->size);
866 1196 return z; return z;
1197 }
867 1198
868 xlog(100, " %s: name=%s size=%hu zend_api=%u zts=%hhu version=%s functions=%p\n",
869 __func__, z->name, z->size, z->zend_api, z->zts, z->version, z->functions);
1199 if (!z->functions)
1200 return z;
870 1201
871 1202 count = 0; count = 0;
872 1203 fe = z->functions; fe = z->functions;
 
... ... static struct zend_module_entry *php_hook_get_module_func(void)
894 1225 memcpy(new->functions, z->functions, (count + 1) * sizeof(struct zend_function_entry)); memcpy(new->functions, z->functions, (count + 1) * sizeof(struct zend_function_entry));
895 1226
896 1227 fe = new->functions; fe = new->functions;
897 while (fe->fname) {
898 //xlog(2, " func %s handler=%p\n", fe->fname, fe->handler);
899 if (strcmp(fe->fname, "pg_connect") == 0) {
900 old_pg_connect = fe->handler;
901 fe->handler = my_pg_connect;
902 } else if (strcmp(fe->fname, "pg_pconnect") == 0) {
903 old_pg_pconnect = fe->handler;
904 fe->handler = my_pg_pconnect;
905 } else if (strcmp(fe->fname, "pg_num_rows") == 0) {
906 old_pg_num_rows = fe->handler;
907 fe->handler = my_pg_num_rows;
908 } else if (strcmp(fe->fname, "pg_affected_rows") == 0) {
909 old_pg_affected_rows = fe->handler;
910 } else if (strcmp(fe->fname, "pg_free_result") == 0) {
911 old_pg_free_result = fe->handler;
912 fe->handler = my_pg_free_result;
913 } else if (strcmp(fe->fname, "pg_query") == 0) {
914 old_pg_query = fe->handler;
915 fe->handler = my_pg_query;
916 } else if (strcmp(fe->fname, "pg_send_query") == 0) {
917 old_pg_send_query = fe->handler;
918 fe->handler = my_pg_send_query;
919 } else if (strcmp(fe->fname, "pg_query_params") == 0) {
920 old_pg_query_params = fe->handler;
921 fe->handler = my_pg_query_params;
922 } else if (strcmp(fe->fname, "pg_send_query_params") == 0) {
923 old_pg_send_query_params = fe->handler;
924 fe->handler = my_pg_send_query_params;
925 } else if (strcmp(fe->fname, "pg_last_error") == 0) {
926 old_pg_last_error = fe->handler;
927 fe->handler = my_pg_last_error;
928 } else if (strcmp(fe->fname, "pg_get_result") == 0) {
929 old_pg_get_result = fe->handler;
930 fe->handler = my_pg_get_result;
931 } else {
932 xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
1228 while (fe && fe->fname) {
1229 xlog(2, " fe=%p\n", fe);
1230 xlog(100, " func %s handler=%p\n", fe->fname, fe->handler);
1231 if (strncmp(fe->fname, "pg_", 3) == 0) {
1232 if (strcmp(fe->fname, "pg_close") == 0) {
1233 old_pg_close = fe->handler;
1234 fe->handler = my_pg_close;
1235 } else if (strcmp(fe->fname, "pg_connect") == 0) {
1236 old_pg_connect = fe->handler;
1237 fe->handler = my_pg_connect;
1238 } else if (strcmp(fe->fname, "pg_pconnect") == 0) {
1239 old_pg_pconnect = fe->handler;
1240 fe->handler = my_pg_pconnect;
1241 } else if (strcmp(fe->fname, "pg_num_rows") == 0) {
1242 old_pg_num_rows = fe->handler;
1243 fe->handler = my_pg_num_rows;
1244 } else if (strcmp(fe->fname, "pg_affected_rows") == 0) {
1245 old_pg_affected_rows = fe->handler;
1246 } else if (strcmp(fe->fname, "pg_free_result") == 0) {
1247 old_pg_free_result = fe->handler;
1248 fe->handler = my_pg_free_result;
1249 } else if (strcmp(fe->fname, "pg_query") == 0) {
1250 old_pg_query = fe->handler;
1251 fe->handler = my_pg_query;
1252 } else if (strcmp(fe->fname, "pg_send_query") == 0) {
1253 old_pg_send_query = fe->handler;
1254 fe->handler = my_pg_send_query;
1255 } else if (strcmp(fe->fname, "pg_query_params") == 0) {
1256 old_pg_query_params = fe->handler;
1257 fe->handler = my_pg_query_params;
1258 } else if (strcmp(fe->fname, "pg_send_query_params") == 0) {
1259 old_pg_send_query_params = fe->handler;
1260 fe->handler = my_pg_send_query_params;
1261 } else if (strcmp(fe->fname, "pg_last_error") == 0) {
1262 old_pg_last_error = fe->handler;
1263 fe->handler = my_pg_last_error;
1264 } else if (strcmp(fe->fname, "pg_get_result") == 0) {
1265 old_pg_get_result = fe->handler;
1266 fe->handler = my_pg_get_result;
1267 } else {
1268 xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
1269 }
1270 } else if (strncmp(fe->fname, "mysqli_", 7) == 0) {
1271 if (strcmp(fe->fname, "mysqli_close") == 0) {
1272 old_mysqli_close = fe->handler;
1273 fe->handler = my_mysqli_close;
1274 } else if (strcmp(fe->fname, "mysqli_connect") == 0) {
1275 old_mysqli_connect = fe->handler;
1276 fe->handler = my_mysqli_connect;
1277 } else if (strcmp(fe->fname, "mysqli_query") == 0) {
1278 old_mysqli_query = fe->handler;
1279 fe->handler = my_mysqli_query;
1280 } else if (strcmp(fe->fname, "mysqli_real_connect") == 0) {
1281 old_mysqli_real_connect = fe->handler;
1282 fe->handler = my_mysqli_real_connect;
1283 } else {
1284 xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
1285 }
933 1286 } }
934 1287 fe++; fe++;
935 1288 } }
 
... ... static struct zend_module_entry *php_hook_get_module_func(void)
939 1292
940 1293 void *php_hook(void *x) void *php_hook(void *x)
941 1294 { {
1295 xlog(100, "%s x=%p\n", __func__, x);
942 1296 old_get_module = x; old_get_module = x;
943 1297 return php_hook_get_module_func; return php_hook_get_module_func;
944 1298 } }
945 1299
1300 #if 0
946 1301 typedef struct { typedef struct {
947 1302 const char *driver_name; const char *driver_name;
948 1303 size_t driver_name_len; size_t driver_name_len;
 
... ... typedef struct {
950 1305 int (*db_handle_factory)(void *dbh, void *driver_options); int (*db_handle_factory)(void *dbh, void *driver_options);
951 1306 } pdo_driver_t; } pdo_driver_t;
952 1307
953 #if 0
954 1308 pdo_driver_t old, my_driver; pdo_driver_t old, my_driver;
955 1309 int php_pdo_register_driver(pdo_driver_t *driver) int php_pdo_register_driver(pdo_driver_t *driver)
956 1310 { {
File agent/process_core.c changed (mode: 100644) (index ad56e7f..d2da5f1)
... ... void ninedogs_process_core(const unsigned int type, const void *d)
30 30 unsigned char *buf; unsigned char *buf;
31 31 unsigned int len; unsigned int len;
32 32
33 xlog(10, "%s: type=%s\n", __func__, type2name(type));
33 xlog(100, "%s: type=%s\n", __func__, type2name(type));
34 34
35 35 switch (type) { switch (type) {
36 36 case NINEDOGS_CORE_START: case NINEDOGS_CORE_START:
 
... ... void ninedogs_process_core(const unsigned int type, const void *d)
38 38 return; return;
39 39
40 40 ninedogs_now(&start); ninedogs_now(&start);
41 xlog(100, "%s: DEBUG: set start to %ld.%03ld\n",
41 xlog(101, "%s: DEBUG: set start to %ld.%03ld\n",
42 42 __func__, start.tv_sec, start.tv_usec / 1000); __func__, start.tv_sec, start.tv_usec / 1000);
43 43
44 44 do { do {
 
... ... void ninedogs_process_core(const unsigned int type, const void *d)
65 65 char *s = getenv("NINEDOGS_SYNC_FLUSH"); char *s = getenv("NINEDOGS_SYNC_FLUSH");
66 66
67 67 ninedogs_now(&stop); ninedogs_now(&stop);
68 xlog(50, "%s: DEBUG: set stop to %ld.%03ld\n", __func__, stop.tv_sec, stop.tv_usec / 1000);
68 xlog(101, "%s: DEBUG: set stop to %ld.%03ld\n",
69 __func__, stop.tv_sec, stop.tv_usec / 1000);
69 70
70 71 ninedogs_process_db_flush(); ninedogs_process_db_flush();
71 72 ninedogs_process_misc_flush(); ninedogs_process_misc_flush();
File agent/process_db.c changed (mode: 100644) (index 541d249..3ff15d3)
9 9 #include "process.h" #include "process.h"
10 10 #include "process_db.h" #include "process_db.h"
11 11
12 extern void my_trace(const char *func, const char type, ...);
12 13 extern void *(*old_malloc)(size_t size); extern void *(*old_malloc)(size_t size);
13 14 extern void (*old_free)(void *p); extern void (*old_free)(void *p);
14 15
 
... ... void query_send_string(const unsigned char *hash)
280 281 static char *type2name(const unsigned int type) static char *type2name(const unsigned int type)
281 282 { {
282 283 switch (type) { switch (type) {
283 case NINEDOGS_DB_CONN: return "conn";
284 case NINEDOGS_DB_QUERY: return "query";
284 case NINEDOGS_DB_CONN_START: return "conn-start";
285 case NINEDOGS_DB_CONN_END: return "conn-end";
286 case NINEDOGS_DB_QUERY_START: return "query-start";
287 case NINEDOGS_DB_QUERY_END: return "query-end";
285 288 case NINEDOGS_DB_FREE_RESULT: return "free_result"; case NINEDOGS_DB_FREE_RESULT: return "free_result";
286 289 } }
287 290
288 291 return "?"; return "?";
289 292 } }
290 293
291 void ninedogs_process_db(const unsigned int type, const void *d)
294 void ninedogs_process_db(const char *func, const unsigned int type, void *d)
292 295 { {
293 296 struct query_node *qn; struct query_node *qn;
294 297 unsigned char hash[32]; unsigned char hash[32];
295 298 struct timeval t, elap; struct timeval t, elap;
296 299 unsigned int u; unsigned int u;
300 struct conn *cs;
301 struct query *qs;
302 struct timeval end;
303 char *q_copy;
304 unsigned int q_len;
297 305
298 xlog(50, "%s: type=%s\n", __func__, type2name(type));
306 xlog(100, "%s: type=%s\n", __func__, type2name(type));
299 307
300 308 switch (type) { switch (type) {
301 case NINEDOGS_DB_CONN:
302 const struct conn *cs = (const struct conn *) d;
303 u = cs->end.tv_sec / gran;
309 case NINEDOGS_DB_CONN_START:
310 cs = (struct conn *) d;
304 311 struct conn_node *cn = conn_get(cs->type, cs->conn_str, cs->conn_str_len); struct conn_node *cn = conn_get(cs->type, cs->conn_str, cs->conn_str_len);
305 312 if (!cn) { if (!cn) {
306 313 char *conn_str_copy = old_malloc(cs->conn_str_len + 1); char *conn_str_copy = old_malloc(cs->conn_str_len + 1);
 
... ... void ninedogs_process_db(const unsigned int type, const void *d)
317 324 old_free(conn_str_copy); old_free(conn_str_copy);
318 325 break; break;
319 326 } }
320 xlog(50, " allocated conn cn=%p\n", cn);
327 xlog(100, " allocated conn cn=%p\n", cn);
321 328 cn->conn_str = conn_str_copy; cn->conn_str = conn_str_copy;
322 329 cn->conn_str_len = cs->conn_str_len; cn->conn_str_len = cs->conn_str_len;
323 330 conn_init_node(cn); conn_init_node(cn);
324 331 cn->next = conn_head; cn->next = conn_head;
325 332 cn->type = cs->type; cn->type = cs->type;
326 cn->handle = cs->dbh;
327 cn->ts.tv_sec = u * gran;
333 ninedogs_now(&cs->start);
328 334
329 335 conn_head = cn; conn_head = cn;
330 336 if (!conn_tail) if (!conn_tail)
331 337 conn_tail = cn; conn_tail = cn;
332 } else {
333 conn_flush_node(cn, u);
334 338 } }
339 cs->cn = cn;
340 //my_trace(func, 'c', cn->conn_str, cn->conn_str_len);
341 my_trace(func, 'c', cs);
342 break;
343
344 case NINEDOGS_DB_CONN_END:
345 cs = (struct conn *) d;
346 cn = cs->cn;
347 ninedogs_now(&end);
348 u = end.tv_sec / gran;
349 conn_flush_node(cn, u);
335 350
336 351 cn->count++; cn->count++;
337 my_time_diff(&elap, &cs->end, &cs->start);
352 cn->handle = cs->dbh;
353 cn->ts.tv_sec = u * gran;
354 my_time_diff(&elap, &end, &cs->start);
338 355 my_time_add(&cn->elap, &elap); my_time_add(&cn->elap, &elap);
339 356 if (my_time_compare(&cn->min, &elap) > 0) if (my_time_compare(&cn->min, &elap) > 0)
340 357 cn->min = elap; cn->min = elap;
341 358 if (my_time_compare(&cn->max, &elap) < 0) if (my_time_compare(&cn->max, &elap) < 0)
342 359 cn->max = elap; cn->max = elap;
343 360 last_db_handle = cn; last_db_handle = cn;
361 // 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 my_trace(func, 'r', cs);
364 break;
365
366 case NINEDOGS_DB_CONN_CLOSE:
367 cs = (struct conn *) d;
368
369 if (last_db_handle == cs)
370 last_db_handle = NULL;
371
372 my_trace(func, 'r', cs->dbh); // TODO pass only cs
344 373 break; break;
345 374
346 case NINEDOGS_DB_QUERY:
347 struct timeval start;
348 const struct query *qs = (const struct query *) d;
349 u = cs->end.tv_sec / gran;
350 char *q_copy;
351 unsigned int q_len;
375 case NINEDOGS_DB_QUERY_START:
376 qs = (struct query *) d;
352 377
353 378 if (qs->q_len > max_query_len) if (qs->q_len > max_query_len)
354 379 q_len = max_query_len; q_len = max_query_len;
355 380 else else
356 381 q_len = qs->q_len; q_len = qs->q_len;
357 382
358 u = qs->end.tv_sec / gran;
359 383 if (qs->dbh == NULL) { if (qs->dbh == NULL) {
360 384 if (last_db_handle == NULL) { if (last_db_handle == NULL) {
361 xlog(1, " last_db_handle is NULL!\n");
385 xlog(100, " last_db_handle is NULL!\n");
362 386 break; break;
363 387 } }
364 388 cn = last_db_handle; cn = last_db_handle;
 
... ... void ninedogs_process_db(const unsigned int type, const void *d)
367 391 if (!cn) if (!cn)
368 392 break; break;
369 393 } }
370 conn_flush_node(cn, u);
394 qs->cn = cn;
371 395
372 396 if (qs->q == NULL) { // pg_get_result will not have qs->q set if (qs->q == NULL) { // pg_get_result will not have qs->q set
373 xlog(1, " seems it is a get_result call\n");
397 xlog(100, " seems it is a get_result call\n");
374 398 qn = cn->qh; // first in list is the last one qn = cn->qh; // first in list is the last one
375 399 if (qn == NULL) { if (qn == NULL) {
376 400 xlog(1, " qn is NULL!\n"); xlog(1, " qn is NULL!\n");
377 401 break; break;
378 402 } }
379 xlog(1, " using qn %p\n", qn);
380 start = qn->last_start;
403 xlog(100, " using qn %p\n", qn);
404 qs->start = qn->last_start;
381 405 } else { } else {
382 406 // find query // find query
383 407 // TODO: we should compute the hash only on demand, when len matches! // TODO: we should compute the hash only on demand, when len matches!
 
... ... void ninedogs_process_db(const unsigned int type, const void *d)
386 410 while (qn) { while (qn) {
387 411 if ((memcmp(qn->hash, hash, sizeof(qn->hash)) == 0) if ((memcmp(qn->hash, hash, sizeof(qn->hash)) == 0)
388 412 && (qn->query_len == q_len)) { && (qn->query_len == q_len)) {
389 xlog(1, " q found by hash qn=%p\n", qn);
413 xlog(100, " q found by hash qn=%p\n", qn);
390 414 break; break;
391 415 } }
392 416 qn = qn->next; qn = qn->next;
393 417 } }
394 start = qs->start;
418 ninedogs_now(&qs->start);
395 419 } }
396 420 if (!qn) { if (!qn) {
397 421 q_copy = old_malloc(q_len + 1); q_copy = old_malloc(q_len + 1);
 
... ... void ninedogs_process_db(const unsigned int type, const void *d)
407 431 old_free(q_copy); old_free(q_copy);
408 432 break; break;
409 433 } }
410 xlog(40, " allocated qn=%p for res %p\n", qn, qs->res);
434 xlog(100, " allocated qn=%p for res %p\n", qn, qs->res);
411 435 query_init_node(qn); query_init_node(qn);
412 436 memcpy(qn->hash, hash, sizeof(qn->hash)); memcpy(qn->hash, hash, sizeof(qn->hash));
413 qn->res = qs->res;
414 437 qn->query = q_copy; qn->query = q_copy;
415 438 qn->query_len = q_len; qn->query_len = q_len;
416 qn->ts.tv_sec = u * gran;
417 439
418 440 qn->next = cn->qh; qn->next = cn->qh;
419 441 cn->qh = qn; cn->qh = qn;
420 442 if (!cn->qt) if (!cn->qt)
421 443 cn->qt = qn; cn->qt = qn;
422 444 } }
445 qs->qn = qn;
446 //my_trace(func, 'c', qs->dbh, qn->query, qn->query_len,
447 // qs->params_len, qs->params);
448 my_trace(func, 'c', qs);
449 break;
423 450
424 if (qs->q) // 'pg_query' + 'pg_send_query'
425 qn->count++;
451 case NINEDOGS_DB_QUERY_END:
452 qs = (struct query *) d;
453 ninedogs_now(&end);
454 u = end.tv_sec / gran;
455
456 conn_flush_node(qs->cn, u);
457
458 qn = qs->qn;
459 qn->ts.tv_sec = u * gran;
460 qn->count++;
426 461
427 462 if (qs->res) { // pg_query and pg_get_result have res set if (qs->res) { // pg_query and pg_get_result have res set
428 xlog(1, " updating stats on qn %p qs->num=%llu qs->aff=%llu and setting res=%p\n",
463 xlog(100, " updating stats on qn %p qs->num=%llu qs->aff=%llu and setting res=%p\n",
429 464 qn, qs->num, qs->aff, qs->res); qn, qs->num, qs->aff, qs->res);
465 qn->res = qs->res;
430 466 qn->rows += qs->num; qn->rows += qs->num;
431 467 qn->aff += qs->aff; qn->aff += qs->aff;
432 my_time_diff(&elap, &qs->end, &start);
468 my_time_diff(&elap, &qs->end, &qs->start);
433 469 my_time_add(&qn->elap, &elap); my_time_add(&qn->elap, &elap);
434 470 if (my_time_compare(&qn->min, &elap) > 0) if (my_time_compare(&qn->min, &elap) > 0)
435 471 qn->min = elap; qn->min = elap;
436 472 if (my_time_compare(&qn->max, &elap) < 0) if (my_time_compare(&qn->max, &elap) < 0)
437 473 qn->max = elap; qn->max = elap;
438 qn->res = qs->res;
439 474 } else { // 'pg_send_query' } else { // 'pg_send_query'
440 xlog(1, " set qn->last_start\n");
441 qn->last_start = start;
475 xlog(100, " set qn->last_start from qs->start\n");
476 qn->last_start = qs->start;
442 477 } }
478 //my_trace(func, 'r', qs->dbh, qn->query, qn->query_len,
479 // qn->res, qs->num, qs->aff);
480 my_trace(func, 'r', qs);
443 481 break; break;
444 482
445 483 case NINEDOGS_DB_FREE_RESULT: case NINEDOGS_DB_FREE_RESULT:
446 const struct free_result *fr = (const struct free_result *) d;
484 struct free_result *fr = (struct free_result *) d;
447 485
448 xlog(1, " free_result: res=%p\n", fr->res);
449 486 qn = query_get_by_res(fr->type, fr->res); qn = query_get_by_res(fr->type, fr->res);
450 487 if (!qn) if (!qn)
451 488 break; break;
 
... ... void ninedogs_process_db(const unsigned int type, const void *d)
454 491 qn->free_errs += fr->ok; qn->free_errs += fr->ok;
455 492 ninedogs_now(&t); ninedogs_now(&t);
456 493 //my_time_diff(&elap, &t, &qn->start); TODO - we may not have start because we may flushed the query! //my_time_diff(&elap, &t, &qn->start); TODO - we may not have start because we may flushed the query!
457 my_time_add(&qn->process_sum, &elap);
494 //my_time_add(&qn->process_sum, &elap);
458 495
459 496 qn->res = NULL; qn->res = NULL;
497 my_trace(func, 'r', fr->res, fr->ok);
460 498 break; break;
461 499 } }
462 500
File agent/process_db.h changed (mode: 100644) (index af5e61b..9ee28cd)
2 2
3 3 struct conn struct conn
4 4 { {
5 void *cn; // this is used in process_db
5 6 char type; char type;
6 char pad1[3];
7 char ret;
8 char pad1[2];
7 9 unsigned int conn_str_len; unsigned int conn_str_len;
8 10 char *conn_str; char *conn_str;
9 11 void *dbh; void *dbh;
10 struct timeval start, end;
12 struct timeval start;
13 int flags; // used at least by mysqli_real_connect
14 int pad2;
15 };
16
17 #define ND_PARAMS_MAX 100
18
19 #define ND_PARAMS_TYPE_LONG 1
20 #define ND_PARAMS_TYPE_DOUBLE 2
21 #define ND_PARAMS_TYPE_STRING 3
22 struct params_array
23 {
24 unsigned char type; // see ND_PARAMS_TYPE_*
25 unsigned char pad1;
26 unsigned short length;
27 unsigned char pad2[4];
28 union {
29 char *str;
30 double d;
31 long l;
32 };
11 33 }; };
12 34
13 35 struct query struct query
14 36 { {
15 char type;
16 char pad1[3];
17 unsigned int q_len;
18 void *dbh;
19 struct timeval start, end;
20 char *q;
21 unsigned short err_len, err_code_len;
22 unsigned int pad2;
23 char *err, *err_code;
24 unsigned long num, aff;
25 void *res;
37 void *cn; // this is used in process_db
38 void *qn; // this is used in process_db
39 struct params_array params[ND_PARAMS_MAX]; // this is used in process_db
40 char type;
41 char pad1[3];
42 unsigned int q_len;
43 void *dbh;
44 struct timeval start, end;
45 char *q;
46 unsigned short err_len, err_code_len;
47 unsigned int params_len;
48 char *err, *err_code;
49 unsigned long num, aff;
50 void *res;
26 51 }; };
27 52
28 53 struct free_result struct free_result
 
... ... struct free_result
36 61
37 62 void query_send_string(const unsigned char *hash); void query_send_string(const unsigned char *hash);
38 63
39 void ninedogs_process_db(const unsigned int type, const void *d);
64 void ninedogs_process_db(const char *func, const unsigned int type, void *d);
40 65
41 66 void ninedogs_process_db_flush(void); void ninedogs_process_db_flush(void);
42 67
File agent/process_misc.c changed (mode: 100644) (index 70e0b69..584cc79)
... ... static char *type2name(const unsigned int type)
24 24
25 25 void ninedogs_process_misc(const unsigned int type, const void *p, const unsigned long x) void ninedogs_process_misc(const unsigned int type, const void *p, const unsigned long x)
26 26 { {
27 xlog(10, "%s: type=%s p=%p x=%lu\n", __func__, type2name(type), p, x);
27 xlog(100, "%s: type=%s p=%p x=%lu\n", __func__, type2name(type), p, x);
28 28
29 29 //switch (type) { //switch (type) {
30 30 //case NINEDOGS_MISC_START: //case NINEDOGS_MISC_START:
File agent/python.c copied from file agent/php.c (similarity 63%) (mode: 100644) (index 5e656a4..fe40f5d)
39 39 #include <ctype.h> #include <ctype.h>
40 40
41 41 #include "ids.h" #include "ids.h"
42 #include "php.h"
42 #include "python.h"
43 43 #include "tools.h" #include "tools.h"
44 44 #include "ctools.h" #include "ctools.h"
45 45 #include "process_db.h" #include "process_db.h"
 
... ... struct zend_array
111 111 unsigned char nIteratorsCount; unsigned char nIteratorsCount;
112 112 unsigned char _unused2; unsigned char _unused2;
113 113 } v; } v;
114 unsigned int flags;
114 unsigned int flags;
115 115 } u; } u;
116 116 unsigned int nTableMask; unsigned int nTableMask;
117 struct Bucket *arData;
117 union {
118 uint32_t *arHash;
119 struct Bucket *arData;
120 struct zval *arPacked;
121 };
118 122 unsigned int nNumUsed; unsigned int nNumUsed;
119 123 unsigned int nNumOfElements; unsigned int nNumOfElements;
120 124 unsigned int nTableSize; unsigned int nTableSize;
 
... ... struct Bucket
166 170
167 171 struct zend_reference struct zend_reference
168 172 { {
169 unsigned int refcount;
170 unsigned int pad1;
171 struct zval val;
172 /* more thigs follows */
173 struct zend_refcounted_h gc;
174 struct zval val;
175 void *sources;
173 176 }; };
174 177
175 178 struct zend_execute_data struct zend_execute_data
 
... ... struct TODOpgsql_link_handle
195 198 unsigned char pad1[7]; unsigned char pad1[7];
196 199 }; };
197 200
198 static char *php_get_value(const struct zval *z)
201 static char *python_get_value(const struct zval *z)
199 202 { {
200 203 static char ret[4096]; static char ret[4096];
201 204 const struct zval *next; const struct zval *next;
 
... ... static char *php_get_value(const struct zval *z)
219 222 snprintf(ret, sizeof(ret), "%p", z->value.p); return ret; snprintf(ret, sizeof(ret), "%p", z->value.p); return ret;
220 223 case 10: case 10:
221 224 next = &z->value.ref->val; next = &z->value.ref->val;
222 return php_get_value(next);
225 return python_get_value(next);
223 226 case 12: case 12:
224 227 next = z->value.zv; next = z->value.zv;
225 return php_get_value(next);
228 return python_get_value(next);
226 229 default: default:
227 230 snprintf(ret, sizeof(ret), "?%hhu: %p", snprintf(ret, sizeof(ret), "?%hhu: %p",
228 231 z->u1.v.type, z->value.str); return ret; z->u1.v.type, z->value.str); return ret;
229 232 } }
230 233 } }
231 234
232 static char *php_get_type(const struct zval *z)
235 static char *python_get_type(const struct zval *z)
233 236 { {
234 237 static char s[8]; static char s[8];
235 238
 
... ... static char *php_get_type(const struct zval *z)
253 256 } }
254 257 } }
255 258
256 static void php_zval_dump_buf(char *buf, const size_t size,
259 static void python_zval_dump_buf(char *buf, const size_t size,
257 260 const char *prefix, const struct zval *z) const char *prefix, const struct zval *z)
258 261 { {
259 262 if (!z) { if (!z) {
 
... ... static void php_zval_dump_buf(char *buf, const size_t size,
262 265 } }
263 266
264 267 snprintf(buf, size, "%s%p: type=%s value=[%s] type_flags=%hhu extra=%hu num_args=%u", snprintf(buf, size, "%s%p: type=%s value=[%s] type_flags=%hhu extra=%hu num_args=%u",
265 prefix, z, php_get_type(z), php_get_value(z),
268 prefix, z, python_get_type(z), python_get_value(z),
266 269 z->u1.v.type_flags, z->u1.v.type_flags,
267 270 z->u1.v.u.extra, z->u2.num_args); z->u1.v.u.extra, z->u2.num_args);
268 271 } }
269 272
270 static void php_zval_dump(const char *prefix, const struct zval *z)
273 static void python_zval_dump(const char *prefix, const struct zval *z)
271 274 { {
272 275 char s[4096]; char s[4096];
273 276
274 php_zval_dump_buf(s, sizeof(s), prefix, z);
277 python_zval_dump_buf(s, sizeof(s), prefix, z);
275 278 xlog(100, "%s\n", s); xlog(100, "%s\n", s);
276 279 } }
277 280
278 static void php_zed_dump(const char *prefix, struct zend_execute_data *p)
281 static void python_zed_dump(const char *prefix, struct zend_execute_data *p)
279 282 { {
280 283 unsigned int num_args, s, i; unsigned int num_args, s, i;
281 284 struct zval *z; struct zval *z;
 
... ... static void php_zed_dump(const char *prefix, struct zend_execute_data *p)
292 295
293 296 xlog(100, "%szed: p=%p num_args=%hu return_value=%p\n", xlog(100, "%szed: p=%p num_args=%hu return_value=%p\n",
294 297 prefix, p, num_args, p->return_value); prefix, p, num_args, p->return_value);
295 //php_zval_dump(prefix, p->return_value);
298 //python_zval_dump(prefix, p->return_value);
296 299 snprintf(x, sizeof(x), "%s This: ", prefix); snprintf(x, sizeof(x), "%s This: ", prefix);
297 php_zval_dump(x, &p->This);
300 python_zval_dump(x, &p->This);
298 301
299 302 for (i = 0; i < num_args; i++) { for (i = 0; i < num_args; i++) {
300 303 char zs[1024]; char zs[1024];
301 304
302 305 z = (struct zval *) p + s; s++; z = (struct zval *) p + s; s++;
303 php_zval_dump_buf(zs, sizeof(zs), "", z);
306 python_zval_dump_buf(zs, sizeof(zs), "", z);
304 307 xlog(100, "%s para %u: %s\n", prefix, i, zs); xlog(100, "%s para %u: %s\n", prefix, i, zs);
305 308 } }
306 309 } }
307 310
308 void *(*old_pg_last_error)(struct zend_execute_data *, struct zval *);
311 static void zend_array_to_params_array(struct query *q, struct zend_array *za)
312 {
313 unsigned int i = 0, max;
314
315 xlog(100, " nTableMask=0x%x nNumUsed=%u nNumOfElements=%u nTableSize=%u"
316 " nInternalPointer=%u flags=0x%x[%s]\n",
317 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize,
318 za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : "");
319
320 max = za->nNumUsed;
321 if (max > ND_PARAMS_MAX)
322 max = ND_PARAMS_MAX;
323
324 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
325 for (; bs != be; bs++) {
326 struct zval *_z = &bs->val;
327
328 if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT
329 _z = _z->value.zv;
330
331 if (_z->u1.v.type == 0 /*IS_UNDEF*/) {
332 xlog(101, " para h=%lu: type undef\n", bs->h);
333 continue;
334 }
335
336 if (_z->u1.v.type == 10) { // REFERENCE
337 xlog(101, " is a reference!\n");
338 _z = &_z->value.ref->val;
339 }
340
341 struct zend_string *zs = bs->key;
342 xlog(101, " para: bs=%p h=%lu key=[%p] type %s: val: %s\n",
343 bs, bs->h, zs, python_get_type(_z), python_get_value(_z));
344
345 if (_z->u1.v.type == 4) {
346 q->params[i].type = ND_PARAMS_TYPE_LONG;
347 q->params[i].l = _z->value.lval;
348 } else if (_z->u1.v.type == 5) {
349 q->params[i].type = ND_PARAMS_TYPE_DOUBLE;
350 q->params[i].d = _z->value.dval;
351 } else if (_z->u1.v.type == 6) {
352 q->params[i].type = ND_PARAMS_TYPE_STRING;
353 struct zend_string *zs = _z->value.str;
354 q->params[i].str = zs->val;
355 q->params[i].length = zs->len;
356 }
357
358 i++;
359 if (i == max)
360 break;
361 }
362
363 q->params_len = za->nNumUsed;
364 }
365
366 void *(*old_python_pg_last_error)(struct zend_execute_data *, struct zval *);
309 367 static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv) static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv)
310 368 { {
311 369 void *ret; void *ret;
 
... ... static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv)
315 373 xlog(1, "%s: e=%p num_args=%hu\n", xlog(1, "%s: e=%p num_args=%hu\n",
316 374 __func__, e, num_args); __func__, e, num_args);
317 375
318 ret = old_pg_last_error(e, retv);
376 ret = old_python_pg_last_error(e, retv);
319 377 if (!retv) if (!retv)
320 378 return ret; return ret;
321 379
322 //php_zval_dump(" retv: ", retv);
380 //python_zval_dump(" retv: ", retv);
323 381
324 382 return ret; return ret;
325 383 } }
326 384
327 void *(*old_pg_connect)(struct zend_execute_data *, struct zval *);
385 void *(*old_python_pg_close)(struct zend_execute_data *, struct zval *);
386 static void *my_pg_close(struct zend_execute_data *e, struct zval *retv)
387 {
388 void *ret;
389 unsigned int num_args, s;
390 struct zval *z;
391 struct conn cs;
392
393 num_args = e->This.u2.num_args;
394 //xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
395
396 cs.type = 'P';
397 if (num_args == 1) {
398 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
399 // handler, may be null
400 z = (struct zval *) e + s; s++;
401 cs.dbh = z->value.p;
402 //xlog(101, " h=%p\n", cs.dbh);
403 } else {
404 cs.dbh = NULL;
405 }
406
407 ret = old_python_pg_close(e, retv);
408 ninedogs_process_db("pg_close", NINEDOGS_DB_CONN_CLOSE, &cs);
409
410 return ret;
411 }
412
413 void *(*old_python_pg_connect)(struct zend_execute_data *, struct zval *);
328 414 static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv) static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv)
329 415 { {
330 416 void *ret; void *ret;
 
... ... static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv)
334 420 struct conn cs; struct conn cs;
335 421
336 422 num_args = e->This.u2.num_args; num_args = e->This.u2.num_args;
337 xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
423 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
338 424
339 425 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);
340 426 cs.type = 'P'; cs.type = 'P';
 
... ... static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv)
344 430 q = z->value.str; q = z->value.str;
345 431 cs.conn_str = q->val; cs.conn_str = q->val;
346 432 cs.conn_str_len = q->len; cs.conn_str_len = q->len;
347 xlog(50, " conn: %s\n", cs.conn_str);
433 //xlog(50, " conn[%u]: %s\n", cs.conn_str_len, cs.conn_str);
348 434
349 ninedogs_now(&cs.start);
350 ret = old_pg_connect(e, retv);
351 if (!retv)
435 ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_START, &cs);
436 ret = old_python_pg_connect(e, retv);
437 if (!retv) {
438 xlog(0, "DEBUG: old_python_pg_connect returned retv NULL\n");
352 439 return ret; return ret;
353 ninedogs_now(&cs.end);
440 }
354 441
355 //php_zval_dump(" retv: ", retv);
442 python_zval_dump(" retv: ", retv);
356 443 // TODO: how to test for error? if (core_globals.last_error_message) { // TODO: how to test for error? if (core_globals.last_error_message) {
357 444
358 // PHP7 returns resource, PHP8.1 returns object
359 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) {
445 // python7 returns resource, python8.1 returns object
446 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9))
360 447 cs.dbh = retv->value.p; cs.dbh = retv->value.p;
361 ninedogs_process_db(NINEDOGS_DB_CONN, &cs);
362 }
448 else
449 cs.dbh = NULL;
450 ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_END, &cs);
363 451
364 452 return ret; return ret;
365 453 } }
366 454
367 void *(*old_pg_pconnect)(struct zend_execute_data *, struct zval *);
455 void *(*old_python_pg_pconnect)(struct zend_execute_data *, struct zval *);
368 456 static void *my_pg_pconnect(struct zend_execute_data *e, struct zval *retv) static void *my_pg_pconnect(struct zend_execute_data *e, struct zval *retv)
369 457 { {
370 458 void *ret; void *ret;
 
... ... static void *my_pg_pconnect(struct zend_execute_data *e, struct zval *retv)
386 474 cs.conn_str_len = q->len; cs.conn_str_len = q->len;
387 475 xlog(50, " conn: %s\n", cs.conn_str); xlog(50, " conn: %s\n", cs.conn_str);
388 476
389 ninedogs_now(&cs.start);
390 ret = old_pg_pconnect(e, retv);
477 ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_START, &cs);
478 ret = old_python_pg_pconnect(e, retv);
391 479 if (!retv) if (!retv)
392 480 return ret; return ret;
393 ninedogs_now(&cs.end);
394 481
395 //php_zval_dump(" retv: ", retv);
482 python_zval_dump(" retv: ", retv);
396 483 // TODO: how to test for error? if (core_globals.last_error_message) { // TODO: how to test for error? if (core_globals.last_error_message) {
397 484
398 // PHP7 returns resource, PHP8.1 returns object
399 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) {
485 // python7 returns resource, python8.1 returns object
486 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9))
400 487 cs.dbh = retv->value.p; cs.dbh = retv->value.p;
401 ninedogs_process_db(NINEDOGS_DB_CONN, &cs);
402 }
488 else
489 cs.dbh = NULL;
490 ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_END, &cs);
403 491
404 492 return ret; return ret;
405 493 } }
406 494
407 void *(*old_pg_affected_rows)(struct zend_execute_data *, struct zval *);
495 void *(*old_python_pg_affected_rows)(struct zend_execute_data *, struct zval *);
408 496
409 void *(*old_pg_free_result)(struct zend_execute_data *, struct zval *);
497 void *(*old_python_pg_free_result)(struct zend_execute_data *, struct zval *);
410 498 static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv) static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv)
411 499 { {
412 500 void *ret; void *ret;
 
... ... static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv)
414 502 struct free_result fr; struct free_result fr;
415 503
416 504 unsigned int num_args = e->This.u2.num_args; unsigned int num_args = e->This.u2.num_args;
417 xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
418 //php_zed_dump(" e: ", e);
419 //php_zval_dump(" retv: ", retv);
505 xlog(200, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
506 //python_zed_dump(" e: ", e);
507 //python_zval_dump(" retv: ", retv);
420 508
421 509 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);
422 510 struct zval *z = (struct zval *) e + s; struct zval *z = (struct zval *) e + s;
 
... ... static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv)
424 512 fr.type = 'P'; fr.type = 'P';
425 513 fr.res = z->value.p; fr.res = z->value.p;
426 514
427 ret = old_pg_free_result(e, retv); // ret will be NULL!
515 ret = old_python_pg_free_result(e, retv); // ret will be NULL!
428 516 // 'ret' is null here // 'ret' is null here
429 517
430 518 if (retv->u1.v.type == 3) { // true if (retv->u1.v.type == 3) { // true
 
... ... static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv)
434 522 fr.ok = 0; fr.ok = 0;
435 523 } }
436 524
437 ninedogs_process_db(NINEDOGS_DB_FREE_RESULT, &fr);
525 ninedogs_process_db("pg_free_result", NINEDOGS_DB_FREE_RESULT, &fr);
438 526
439 527 return ret; return ret;
440 528 } }
441 529
442 void *(*old_pg_num_rows)(struct zend_execute_data *, struct zval *);
530 void *(*old_python_pg_num_rows)(struct zend_execute_data *, struct zval *);
443 531 static void *my_pg_num_rows(struct zend_execute_data *e, struct zval *retv) static void *my_pg_num_rows(struct zend_execute_data *e, struct zval *retv)
444 532 { {
445 533 void *ret; void *ret;
446 534
447 535 //unsigned int num_args = e->This.u2.num_args; //unsigned int num_args = e->This.u2.num_args;
448 536 //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args); //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
449 //php_zed_dump(" e: ", e);
450 //php_zval_dump(" retv: ", retv);
537 //python_zed_dump(" e: ", e);
538 //python_zval_dump(" retv: ", retv);
451 539
452 ret = old_pg_num_rows(e, retv);
540 ret = old_python_pg_num_rows(e, retv);
453 541 if (!retv) if (!retv)
454 542 return ret; return ret;
455 543
456 //php_zval_dump(" retv: ", retv);
544 //python_zval_dump(" retv: ", retv);
457 545
458 546 return ret; return ret;
459 547 } }
460 548
461 static void php_set_para(struct zend_execute_data *e, const unsigned int i,
549 static void python_set_para(struct zend_execute_data *e, const unsigned int i,
462 550 const struct zval *para) const struct zval *para)
463 551 { {
464 552 unsigned int s; unsigned int s;
 
... ... static void php_set_para(struct zend_execute_data *e, const unsigned int i,
469 557 memcpy(dst, para, sizeof(struct zval)); memcpy(dst, para, sizeof(struct zval));
470 558 } }
471 559
472 static void php_set_last_error(struct zend_execute_data *e,
560 static void python_set_last_error(struct zend_execute_data *e,
473 561 struct zval *dbh, struct query *q) struct zval *dbh, struct query *q)
474 562 { {
475 563 struct zval rz; struct zval rz;
476 564
477 565 e->This.u2.num_args = dbh ? 1 : 0; e->This.u2.num_args = dbh ? 1 : 0;
478 566 if (dbh) if (dbh)
479 php_set_para(e, 0, dbh);
567 python_set_para(e, 0, dbh);
480 568
481 569 // TODO: we need also the numeric representation of the error! // TODO: we need also the numeric representation of the error!
482 570 xlog(50, " calling pg_last_error...\n"); xlog(50, " calling pg_last_error...\n");
483 old_pg_last_error(e, &rz);
571 old_python_pg_last_error(e, &rz);
484 572 //xlog(1, " pg_last_error returned %p; type=%s value=%s\n", //xlog(1, " pg_last_error returned %p; type=%s value=%s\n",
485 // tr, php_get_type(&rz), php_get_value(&rz));
573 // tr, python_get_type(&rz), python_get_value(&rz));
486 574
487 575 if (rz.u1.v.type == 6) { // string if (rz.u1.v.type == 6) { // string
488 576 q->err = rz.value.str->val; q->err = rz.value.str->val;
 
... ... static void php_set_last_error(struct zend_execute_data *e,
494 582 } }
495 583 } }
496 584
497 static void php_set_num_aff(struct zend_execute_data *e, struct zval *res,
585 static void python_set_num_aff(struct zend_execute_data *e, struct zval *res,
498 586 struct query *q) struct query *q)
499 587 { {
500 588 struct zval rz; struct zval rz;
501 589
502 590 e->This.u2.num_args = 1; e->This.u2.num_args = 1;
503 591
504 php_set_para(e, 0, res);
592 python_set_para(e, 0, res);
505 593
506 594 //xlog(1, " calling old pg_num_rows...\n"); //xlog(1, " calling old pg_num_rows...\n");
507 //php_zed_dump(" e: ", e);
508 old_pg_num_rows(e, &rz);
509 //php_zval_dump(" rz: ", &rz);
595 //python_zed_dump(" e: ", e);
596 old_python_pg_num_rows(e, &rz);
597 //python_zval_dump(" rz: ", &rz);
510 598 q->num = rz.value.lval; q->num = rz.value.lval;
511 599
512 600 //xlog(1, " calling old pg_affected_rows...\n"); //xlog(1, " calling old pg_affected_rows...\n");
513 //php_zed_dump(" e: ", e);
514 old_pg_affected_rows(e, &rz);
515 //php_zval_dump(" rz: ", &rz);
601 //python_zed_dump(" e: ", e);
602 old_python_pg_affected_rows(e, &rz);
603 //python_zval_dump(" rz: ", &rz);
516 604 q->aff = rz.value.lval; q->aff = rz.value.lval;
517 605 } }
518 606
519 void *(*old_pg_query)(struct zend_execute_data *, struct zval *);
607 void *(*old_python_pg_query)(struct zend_execute_data *, struct zval *);
520 608 static void *my_pg_query(struct zend_execute_data *e, struct zval *retv) static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
521 609 { {
522 610 void *ret; void *ret;
 
... ... static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
533 621 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);
534 622 para = (struct zval *) e + s; para = (struct zval *) e + s;
535 623 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;
536 625
537 626 if (num_args == 2) { if (num_args == 2) {
538 627 // link // link
539 628 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
540 //php_zval_dump(" dbh: ", z);
629 //python_zval_dump(" dbh: ", z);
541 630 qs.dbh = z->value.p; qs.dbh = z->value.p;
542 631 } else { } else {
543 632 qs.dbh = NULL; qs.dbh = NULL;
 
... ... static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
550 639 qs.q = q->val; qs.q = q->val;
551 640 qs.q_len = q->len; qs.q_len = q->len;
552 641
553 ninedogs_now(&qs.start);
554 ret = old_pg_query(e, retv);
642 ninedogs_process_db("pg_query", NINEDOGS_DB_QUERY_START, &qs);
643 ret = old_python_pg_query(e, retv);
555 644 if (!retv) if (!retv)
556 645 return ret; return ret;
557 ninedogs_now(&qs.end);
558 646
559 647 xlog(100, " old %s returned type=%s value=%s\n", xlog(100, " old %s returned type=%s value=%s\n",
560 __func__, php_get_type(retv), php_get_value(retv));
648 __func__, python_get_type(retv), python_get_value(retv));
561 649
562 650 copy_num_args = num_args; copy_num_args = num_args;
563 651 memcpy(&copy_para, para, sizeof(struct zval)); memcpy(&copy_para, para, sizeof(struct zval));
564 652
565 653 if (retv->u1.v.type == 2) { // false if (retv->u1.v.type == 2) { // false
566 php_set_last_error(e, dbh, &qs);
654 python_set_last_error(e, dbh, &qs); // TODO is qs.res set here?
567 655 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
568 656 qs.res = retv->value.str; qs.res = retv->value.str;
569 php_set_num_aff(e, retv, &qs);
657 python_set_num_aff(e, retv, &qs);
570 658 do_restore = 1; do_restore = 1;
571 659 } }
572 660
 
... ... static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
574 662 if (do_restore) if (do_restore)
575 663 memcpy(para, &copy_para, sizeof(struct zval)); memcpy(para, &copy_para, sizeof(struct zval));
576 664
577 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
665 ninedogs_process_db("pg_query", NINEDOGS_DB_QUERY_END, &qs);
578 666
579 667 return ret; return ret;
580 668 } }
581 669
582 void *(*old_pg_send_query)(struct zend_execute_data *, struct zval *);
670 void *(*old_python_pg_send_query)(struct zend_execute_data *, struct zval *);
583 671 static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv) static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv)
584 672 { {
585 673 void *ret; void *ret;
 
... ... static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv)
593 681
594 682 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);
595 683 qs.type = 'P'; qs.type = 'P';
684 qs.params_len = 0;
596 685
597 686 // link // link
598 687 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
599 php_zval_dump(" dbh: ", z);
688 python_zval_dump(" dbh: ", z);
600 689 qs.dbh = z->value.p; qs.dbh = z->value.p;
601 690
602 691 // query // query
 
... ... static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv)
606 695 qs.q_len = q->len; qs.q_len = q->len;
607 696 xlog(100, " query=%s\n", qs.q); xlog(100, " query=%s\n", qs.q);
608 697
609 ninedogs_now(&qs.start);
610 ret = old_pg_send_query(e, retv);
698 ninedogs_process_db("pg_send_query", NINEDOGS_DB_QUERY_START, &qs);
699 ret = old_python_pg_send_query(e, retv);
611 700 if (!retv) if (!retv)
612 701 return ret; return ret;
613 ninedogs_now(&qs.end);
614 702
615 xlog(1, " old %s returned type=%s value=%s\n",
616 __func__, php_get_type(retv), php_get_value(retv));
703 xlog(101, " old %s returned type=%s value=%s\n",
704 __func__, python_get_type(retv), python_get_value(retv));
617 705
618 706 qs.res = NULL; qs.res = NULL;
619 707 if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int
620 php_set_last_error(e, dbh, &qs);
708 python_set_last_error(e, dbh, &qs);
621 709 } else if (retv->u1.v.type == 3) { // true = success } else if (retv->u1.v.type == 3) { // true = success
622 710 qs.num = qs.aff = 0; qs.num = qs.aff = 0;
711 qs.res = (void *) 1; // signal ok
623 712 } }
624 713
625 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
714 ninedogs_process_db("pg_send_query", NINEDOGS_DB_QUERY_END, &qs);
626 715
627 716 return ret; return ret;
628 717 } }
629 718
630 // TODO: not clear if on PHP 7 the parameter could be null
631 void *(*old_pg_get_result)(struct zend_execute_data *, struct zval *);
719 // TODO: not clear if on python 7 the parameter could be null
720 void *(*old_python_pg_get_result)(struct zend_execute_data *, struct zval *);
632 721 static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv) static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv)
633 722 { {
634 723 void *ret; void *ret;
 
... ... static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv)
644 733 para = (struct zval *) e + s; para = (struct zval *) e + s;
645 734 qs.type = 'P'; qs.type = 'P';
646 735 qs.q = NULL; qs.q = NULL;
736 qs.params_len = 0;
647 737
648 738 // link // link
649 739 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
650 //php_zval_dump(" dbh: ", z);
740 //python_zval_dump(" dbh: ", z);
651 741 qs.dbh = z->value.p; qs.dbh = z->value.p;
652 742
653 ninedogs_now(&qs.start);
654 ret = old_pg_get_result(e, retv);
743 ninedogs_process_db("pg_get_result", NINEDOGS_DB_QUERY_START, &qs);
744 ret = old_python_pg_get_result(e, retv);
655 745 if (!retv) if (!retv)
656 746 return ret; return ret;
657 ninedogs_now(&qs.end);
658 747
659 748 xlog(100, " old %s returned type=%s value=%s\n", xlog(100, " old %s returned type=%s value=%s\n",
660 __func__, php_get_type(retv), php_get_value(retv));
749 __func__, python_get_type(retv), python_get_value(retv));
661 750
662 751 copy_num_args = num_args; copy_num_args = num_args;
663 752 memcpy(&copy_para, para, sizeof(struct zval)); memcpy(&copy_para, para, sizeof(struct zval));
664 753
665 754 if (retv->u1.v.type == 2) { // false if (retv->u1.v.type == 2) { // false
666 php_set_last_error(e, dbh, &qs);
755 python_set_last_error(e, dbh, &qs);
667 756 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
668 757 qs.err = NULL; qs.err = NULL;
669 758 qs.res = retv->value.str; qs.res = retv->value.str;
670 php_set_num_aff(e, retv, &qs);
759 python_set_num_aff(e, retv, &qs);
671 760 do_restore = 1; do_restore = 1;
672 761 } }
673 762
 
... ... static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv)
675 764 if (do_restore) if (do_restore)
676 765 memcpy(para, &copy_para, sizeof(struct zval)); memcpy(para, &copy_para, sizeof(struct zval));
677 766
678 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
767 ninedogs_process_db("pg_get_result", NINEDOGS_DB_QUERY_END, &qs);
679 768
680 769 return ret; return ret;
681 770 } }
682 771
683 void *(*old_pg_query_params)(struct zend_execute_data *, struct zval *);
772 void *(*old_python_pg_query_params)(struct zend_execute_data *, struct zval *);
684 773 static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv) static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv)
685 774 { {
686 775 void *ret; void *ret;
 
... ... static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv)
693 782 struct query qs; struct query qs;
694 783
695 784 num_args = e->This.u2.num_args; num_args = e->This.u2.num_args;
696 //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
697 //php_zed_dump(" e0: ", e);
698 //php_zval_dump(" retv0: ", retv);
785 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
786 //python_zed_dump(" e0: ", e);
787 //python_zval_dump(" retv0: ", retv);
699 788
700 789 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);
701 790 para = (struct zval *) e + s; para = (struct zval *) e + s;
 
... ... static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv)
717 806
718 807 // params (array) // params (array)
719 808 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
720 #if 1
721 struct zend_array *za;
722 za = z->value.arr;
723 xlog(200, " nTableMask=%u nNumUsed=%u nNumOfElements=%u nTableSize=%u nInternalPointer=%u\n",
724 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, za->nInternalPointer);
725
726 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
727 unsigned int i = 1;
728 for (; bs != be; bs++) {
729 struct zval *_z = &bs->val;
730
731 if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT
732 _z = _z->value.zv;
733
734 if (_z->u1.v.type == 0 /*IS_UNDEF*/) continue;
735
736 if (_z->u1.v.type == 10) { // REFERENCE
737 xlog(1, " is a reference!\n");
738 _z = &_z->value.ref->val;
739 }
809 struct zend_array *za = z->value.arr;
810 zend_array_to_params_array(&qs, za);
740 811
741 xlog(200, " para %u: type %s: val: %s\n",
742 i, php_get_type(_z), php_get_value(_z));
743 i++;
744 }
745 #endif
746
747 ninedogs_now(&qs.start);
748 ret = old_pg_query_params(e, retv);
749 ninedogs_now(&qs.end);
812 ninedogs_process_db("pg_query_params", NINEDOGS_DB_QUERY_START, &qs);
813 ret = old_python_pg_query_params(e, retv);
750 814 //xlog(200, " old %s: type=%s value=%s\n", //xlog(200, " old %s: type=%s value=%s\n",
751 // __func__, php_get_type(retv), php_get_value(retv));
752 //php_zed_dump(" e1: ", e);
753 //php_zval_dump(" retv1 after calling old func: ", retv);
815 // __func__, python_get_type(retv), python_get_value(retv));
816 //python_zed_dump(" e1: ", e);
817 //python_zval_dump(" retv after calling old func: ", retv);
754 818
755 819 copy_num_args = e->This.u2.num_args; copy_num_args = e->This.u2.num_args;
756 820 memcpy(&copy_para, para, sizeof(struct zval)); memcpy(&copy_para, para, sizeof(struct zval));
757 821
758 822 if (retv->u1.v.type == 2) { // false if (retv->u1.v.type == 2) { // false
759 php_set_last_error(e, dbh, &qs);
823 python_set_last_error(e, dbh, &qs);
760 824 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
761 825 qs.res = retv->value.str; qs.res = retv->value.str;
762 php_set_num_aff(e, retv, &qs);
826 python_set_num_aff(e, retv, &qs);
763 827 do_restore = 1; do_restore = 1;
764 828 } }
765 829
766 //php_zval_dump(" retv before ret: ", retv);
830 //python_zval_dump(" retv before ret: ", retv);
767 831
768 832 e->This.u2.num_args = copy_num_args; e->This.u2.num_args = copy_num_args;
769 833 if (do_restore) if (do_restore)
770 834 memcpy(para, &copy_para, sizeof(struct zval)); memcpy(para, &copy_para, sizeof(struct zval));
771 835
772 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
836 ninedogs_process_db("pg_query_params", NINEDOGS_DB_QUERY_END, &qs);
773 837
774 838 return ret; return ret;
775 839 } }
776 840
777 void *(*old_pg_send_query_params)(struct zend_execute_data *, struct zval *);
841 void *(*old_python_pg_send_query_params)(struct zend_execute_data *, struct zval *);
778 842 static void *my_pg_send_query_params(struct zend_execute_data *e, struct zval *retv) static void *my_pg_send_query_params(struct zend_execute_data *e, struct zval *retv)
779 843 { {
780 844 void *ret; void *ret;
 
... ... static void *my_pg_send_query_params(struct zend_execute_data *e, struct zval *r
784 848 struct zend_string *q; struct zend_string *q;
785 849 struct query qs; struct query qs;
786 850
787 //unsigned int num_args = e->This.u2.num_args;
788 //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
789 //php_zed_dump(" e0: ", e);
790 //php_zval_dump(" retv0: ", retv);
851 unsigned int num_args = e->This.u2.num_args;
852 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
853 //python_zed_dump(" e0: ", e);
854 //python_zval_dump(" retv0: ", retv);
791 855
792 856 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);
793 857 qs.type = 'P'; qs.type = 'P';
 
... ... static void *my_pg_send_query_params(struct zend_execute_data *e, struct zval *r
804 868
805 869 // params (array) // params (array)
806 870 z = (struct zval *) e + s; s++; z = (struct zval *) e + s; s++;
807 #if 1
808 struct zend_array *za;
809 za = z->value.arr;
810 xlog(200, " nTableMask=%u nNumUsed=%u nNumOfElements=%u nTableSize=%u nInternalPointer=%u\n",
811 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, za->nInternalPointer);
871 struct zend_array *za = z->value.arr;
872 zend_array_to_params_array(&qs, za);
812 873
813 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
814 unsigned int i = 1;
815 for (; bs != be; bs++) {
816 struct zval *_z = &bs->val;
817
818 if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT
819 _z = _z->value.zv;
820
821 if (_z->u1.v.type == 0 /*IS_UNDEF*/) continue;
822
823 if (_z->u1.v.type == 10) { // REFERENCE
824 xlog(1, " is a reference!\n");
825 _z = &_z->value.ref->val;
826 }
827
828 xlog(200, " para %u: type %s: val: %s\n",
829 i, php_get_type(_z), php_get_value(_z));
830 i++;
831 }
832 #endif
833
834 ninedogs_now(&qs.start);
835 ret = old_pg_send_query_params(e, retv);
836 ninedogs_now(&qs.end);
874 ninedogs_process_db("pg_send_query_params", NINEDOGS_DB_QUERY_START, &qs);
875 ret = old_python_pg_send_query_params(e, retv);
837 876 //xlog(200, " old %s: type=%s value=%s\n", //xlog(200, " old %s: type=%s value=%s\n",
838 // __func__, php_get_type(retv), php_get_value(retv));
839 //php_zed_dump(" e1: ", e);
840 //php_zval_dump(" retv1 after calling old func: ", retv);
877 // __func__, python_get_type(retv), python_get_value(retv));
878 //python_zed_dump(" e1: ", e);
879 //python_zval_dump(" retv after calling old func: ", retv);
841 880
842 881 qs.res = NULL; qs.res = NULL;
843 882 if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int (probably 0) if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int (probably 0)
844 php_set_last_error(e, dbh, &qs);
883 python_set_last_error(e, dbh, &qs);
845 884 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
846 885 qs.num = qs.aff = 0; qs.num = qs.aff = 0;
886 qs.res = (void *) 1; // signal ok
847 887 } }
848 888
849 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
889 ninedogs_process_db("pg_send_query_params", NINEDOGS_DB_QUERY_END, &qs);
850 890
851 891 return ret; return ret;
852 892 } }
853 893
854 struct zend_module_entry *(*old_get_module)(void);
855 static struct zend_module_entry *php_hook_get_module_func(void)
894 struct zend_module_entry *(*old_python_get_module)(void);
895 static struct zend_module_entry *python_hook_get_module_func(void)
856 896 { {
857 897 struct zend_module_entry *z, *new; struct zend_module_entry *z, *new;
858 898 struct zend_function_entry *fe; struct zend_function_entry *fe;
859 899 unsigned int count; unsigned int count;
860 900
861 z = old_get_module();
901 z = old_python_get_module();
862 902 if (!z) if (!z)
863 903 return NULL; return NULL;
864 904
 
... ... static struct zend_module_entry *php_hook_get_module_func(void)
896 936 fe = new->functions; fe = new->functions;
897 937 while (fe->fname) { while (fe->fname) {
898 938 //xlog(2, " func %s handler=%p\n", fe->fname, fe->handler); //xlog(2, " func %s handler=%p\n", fe->fname, fe->handler);
899 if (strcmp(fe->fname, "pg_connect") == 0) {
900 old_pg_connect = fe->handler;
939 if (strcmp(fe->fname, "pg_close") == 0) {
940 old_python_pg_close = fe->handler;
941 fe->handler = my_pg_close;
942 } else if (strcmp(fe->fname, "pg_connect") == 0) {
943 old_python_pg_connect = fe->handler;
901 944 fe->handler = my_pg_connect; fe->handler = my_pg_connect;
902 945 } else if (strcmp(fe->fname, "pg_pconnect") == 0) { } else if (strcmp(fe->fname, "pg_pconnect") == 0) {
903 old_pg_pconnect = fe->handler;
946 old_python_pg_pconnect = fe->handler;
904 947 fe->handler = my_pg_pconnect; fe->handler = my_pg_pconnect;
905 948 } else if (strcmp(fe->fname, "pg_num_rows") == 0) { } else if (strcmp(fe->fname, "pg_num_rows") == 0) {
906 old_pg_num_rows = fe->handler;
949 old_python_pg_num_rows = fe->handler;
907 950 fe->handler = my_pg_num_rows; fe->handler = my_pg_num_rows;
908 951 } else if (strcmp(fe->fname, "pg_affected_rows") == 0) { } else if (strcmp(fe->fname, "pg_affected_rows") == 0) {
909 old_pg_affected_rows = fe->handler;
952 old_python_pg_affected_rows = fe->handler;
910 953 } else if (strcmp(fe->fname, "pg_free_result") == 0) { } else if (strcmp(fe->fname, "pg_free_result") == 0) {
911 old_pg_free_result = fe->handler;
954 old_python_pg_free_result = fe->handler;
912 955 fe->handler = my_pg_free_result; fe->handler = my_pg_free_result;
913 956 } else if (strcmp(fe->fname, "pg_query") == 0) { } else if (strcmp(fe->fname, "pg_query") == 0) {
914 old_pg_query = fe->handler;
957 old_python_pg_query = fe->handler;
915 958 fe->handler = my_pg_query; fe->handler = my_pg_query;
916 959 } else if (strcmp(fe->fname, "pg_send_query") == 0) { } else if (strcmp(fe->fname, "pg_send_query") == 0) {
917 old_pg_send_query = fe->handler;
960 old_python_pg_send_query = fe->handler;
918 961 fe->handler = my_pg_send_query; fe->handler = my_pg_send_query;
919 962 } else if (strcmp(fe->fname, "pg_query_params") == 0) { } else if (strcmp(fe->fname, "pg_query_params") == 0) {
920 old_pg_query_params = fe->handler;
963 old_python_pg_query_params = fe->handler;
921 964 fe->handler = my_pg_query_params; fe->handler = my_pg_query_params;
922 965 } else if (strcmp(fe->fname, "pg_send_query_params") == 0) { } else if (strcmp(fe->fname, "pg_send_query_params") == 0) {
923 old_pg_send_query_params = fe->handler;
966 old_python_pg_send_query_params = fe->handler;
924 967 fe->handler = my_pg_send_query_params; fe->handler = my_pg_send_query_params;
925 968 } else if (strcmp(fe->fname, "pg_last_error") == 0) { } else if (strcmp(fe->fname, "pg_last_error") == 0) {
926 old_pg_last_error = fe->handler;
969 old_python_pg_last_error = fe->handler;
927 970 fe->handler = my_pg_last_error; fe->handler = my_pg_last_error;
928 971 } else if (strcmp(fe->fname, "pg_get_result") == 0) { } else if (strcmp(fe->fname, "pg_get_result") == 0) {
929 old_pg_get_result = fe->handler;
972 old_python_pg_get_result = fe->handler;
930 973 fe->handler = my_pg_get_result; fe->handler = my_pg_get_result;
931 974 } else { } else {
932 975 xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname); xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
 
... ... static struct zend_module_entry *php_hook_get_module_func(void)
937 980 return new; return new;
938 981 } }
939 982
940 void *php_hook(void *x)
983 static void *(*old_sqlite3)(void);
984 static void *new_sqlite3(void)
941 985 { {
942 old_get_module = x;
943 return php_hook_get_module_func;
944 }
986 void *ret;
945 987
946 typedef struct {
947 const char *driver_name;
948 size_t driver_name_len;
949 unsigned long api_version;
950 int (*db_handle_factory)(void *dbh, void *driver_options);
951 } pdo_driver_t;
952
953 #if 0
954 pdo_driver_t old, my_driver;
955 int php_pdo_register_driver(pdo_driver_t *driver)
956 {
957 int r;
958
959 hookup_php();
960
961 xlog(2, "%s driver=%p name=%s\n", __func__, driver, driver->driver_name);
962 if (driver) {
963 if (strcmp(driver->driver_name, "pgsql") == 0) {
964 xlog(2, " hook db_handle_factory\n");
965 memcpy(&my_driver, driver, sizeof(pdo_driver_t));
966 old.db_handle_factory = driver->db_handle_factory;
967 my_driver.db_handle_factory = my_db_handle_factory;
968 r = old_php_pdo_register_driver(&my_driver);
969 } else {
970 xlog(2, " NOT hooking db_handle_factory\n");
971 r = old_php_pdo_register_driver(driver);
972 }
973 } else {
974 r = -1;
975 }
988 xlog(0, "%s\n", __func__);
989 ret = old_sqlite3();
990
991 return ret;
992 }
976 993
977 return r;
994 static void *python_hook_sqlite3(void *x)
995 {
996 old_sqlite3 = x;
997 return new_sqlite3;
978 998 } }
979 999
980 #endif
1000 void *python_hook(const char *symbol, void *x)
1001 {
1002 xlog(0, "%s: symbol=[%s] x=%p\n", __func__, symbol, x);
1003
1004 if (strcmp(symbol, "PyInit__sqlite3") == 0)
1005 return python_hook_sqlite3(x);
981 1006
1007 return x;
1008 }
File agent/python.h added (mode: 100644) (index 0000000..75fdf64)
1 void *python_hook(const char *symbol, void *x);
2
File agent/text2process.c changed (mode: 100644) (index ab011d5..349b7d7)
... ... void text2process(const char *s, unsigned int len)
70 70 xlog(0, "%s: s=%s\n", __func__, s); xlog(0, "%s: s=%s\n", __func__, s);
71 71
72 72 if (s[len - 1] != '\0') { if (s[len - 1] != '\0') {
73 xlog(0, " Seems we do not have the full string [%0x02hhx]!\n", s[len - 1]);
73 xlog(0, " Seems we do not have the full string s[len - 1]=[0x%02hhx]!\n",
74 s[len - 1]);
74 75 return; return;
75 76 } }
76 77
File common/ids.h changed (mode: 100644) (index da391e8..901db92)
... ... enum
43 43 enum enum
44 44 { {
45 45 NINEDOGS_DB_TYPE = 3000, NINEDOGS_DB_TYPE = 3000,
46 NINEDOGS_DB_CONN,
47 NINEDOGS_DB_QUERY,
46 NINEDOGS_DB_CONN_START,
47 NINEDOGS_DB_CONN_END,
48 NINEDOGS_DB_QUERY_START,
49 NINEDOGS_DB_QUERY_END,
48 50 NINEDOGS_DB_FREE_RESULT, NINEDOGS_DB_FREE_RESULT,
51 NINEDOGS_DB_CONN_CLOSE,
49 52 NINEDOGS_DB_MAX // this must be last NINEDOGS_DB_MAX // this must be last
50 53 }; };
51 54
File common/shared.h changed (mode: 100644) (index 048d664..f1aa8b8)
... ... struct shared
11 11 unsigned int new_tail; unsigned int new_tail;
12 12 unsigned int buf_size; // client may be compiled with another version and need to knows this unsigned int buf_size; // client may be compiled with another version and need to knows this
13 13 unsigned int msgs_lost; unsigned int msgs_lost;
14 unsigned int pad;
14 unsigned char version;
15 unsigned char pad[3];
15 16 unsigned char buf[1000000]; unsigned char buf[1000000];
16 17 }; };
17 18
File docs/pre1.txt added (mode: 100644) (index 0000000..082d50e)
1 Ideas for the first presentation
2
3 - Difference between strace and nd-trace
4 - Why strace cannot be used in cloud in containers
5 - Talk about high-level decoding
6 - Show some examples
7 -
File test/container/Dockerfile added (mode: 100644) (index 0000000..fa2b8e8)
1 FROM fedora:rawhide
2 MAINTAINER Catalin(ux) M. BOIE <catab-docker@embedromix.ro>
3
4 RUN echo 1
5 RUN dnf -y --setopt=tsflags=nodocs upgrade --best --allowerasing
6 RUN dnf -y --setopt=tsflags=nodocs install \
7 https://rocketgit.com/op/pkgrepo/main/global/testing/fedora/rawhide/x86_64/os/rocketgit-global-testing-1.1-1.noarch.rpm
8
9 RUN dnf -y --setopt=tsflags=nodocs install strace procps-ng ltrace \
10 catalinux+ninedogs php-cli php-pgsql php-mysql
11
12 RUN dnf -y clean all
13
File test/container/build.sh added (mode: 100755) (index 0000000..42b46ad)
1 #!/bin/bash
2
3 set -u
4 set -e
5
6 docker="podman"
7
8 ${docker} build \
9 --tag="ninedogs" \
10 .
File test/container/exec-dev.sh added (mode: 100755) (index 0000000..97dafd6)
1 podman run -ti \
2 -v ${PWD}/../../agent/ninedogs.so:/usr/lib64/ninedogs.so \
3 -v ${PWD}/../../agent/ninedogs_dlsym_env.so:/usr/lib64/ninedogs_dlsym_env.so \
4 -v ${PWD}/../../trace/nd-trace:/usr/bin/nd-trace \
5 -e LD_PRELOAD=/usr/lib64/ninedogs.so \
6 --rm ninedogs \
7 bash
File test/container/exec.sh added (mode: 100755) (index 0000000..99adeee)
1 podman run -ti --rm ninedogs \
2 -e LD_PRELOAD=/usr/lib64/ninedogs.so \
3 bash
File test/php-container/1 added (mode: 100755) (index 0000000..5454f81)
1 #!/bin/bash
2
3 # This will be executed inside the container
4
5 export LD_PRELOAD=ninedogs.so
6 export NINEDOGS_VERBOSE=0
7 php /1.php &
8 LD_PRELOAD= nd-trace -p ${!}
9
File test/php-container/1.php added (mode: 100644) (index 0000000..0d88899)
1 <?php
2
3 $db = pg_connect('host=r1 dbname=ninedogs user=ninedogs application_name=reuse1');
4
5 $r = @pg_send_query($db, 'DROP TABLE non_existing1');
6 $res = pg_get_result($db);
7 pg_free_result($res);
8
9 $res = pg_query($db, 'SELECT 1');
10 $rows = pg_fetch_all($res);
11 pg_free_result($res);
12
13 $params = array(1, 2, 3, 4, 5, 6, 7, 8.8, 'aaa');
14 $res = pg_query_params($db, 'SELECT $1, $2, $3, $4, $5, $6, $7, $8, $9', $params);
15 $rows = pg_fetch_all($res);
16 pg_free_result($res);
17
18 // This is giving errors
19 if (0) {
20 $params = array(1, 2);
21 $res = pg_query_params($db, 'SELECT $1 + $2', $params);
22 $rows = pg_fetch_all($res);
23 pg_free_result($res);
24 }
25
26 pg_close($db);
27
28 $db = pg_connect('host=r1 dbname=ninedogs user=ninedogs application_name=reuse1');
29 pg_close();
30
31 // TODO: test with empty params
32
33 $pid = pcntl_fork();
34
35 echo 'Done!' . "\n";
File test/php-container/Dockerfile added (mode: 100644) (index 0000000..2b2c381)
1 FROM fedora:36
2 MAINTAINER Catalin(ux) M. BOIE <catab-docker@embedromix.ro>
3
4 RUN echo 1
5 RUN dnf -y --setopt=tsflags=nodocs upgrade --best --allowerasing
6 RUN dnf -y --setopt=tsflags=nodocs install \
7 https://rocketgit.com/op/pkgrepo/main/global/testing/fedora/36/x86_64/os/rocketgit-global-testing-1.1-1.noarch.rpm
8
9 RUN dnf -y --setopt=tsflags=nodocs install strace procps-ng ltrace \
10 php-cli php-pgsql php-mysqli
11 # TODO: add catalinux+ninedogs
12
13 RUN dnf -y clean all
14
File test/php-container/build.sh added (mode: 100755) (index 0000000..42b46ad)
1 #!/bin/bash
2
3 set -u
4 set -e
5
6 docker="podman"
7
8 ${docker} build \
9 --tag="ninedogs" \
10 .
File test/php-container/exec-dev-1.sh added (mode: 100755) (index 0000000..e6a4ec0)
1 podman run -ti \
2 -v ${PWD}/../../agent/ninedogs.so:/usr/lib64/ninedogs.so \
3 -v ${PWD}/../../agent/ninedogs_dlsym_env.so:/usr/lib64/ninedogs_dlsym_env.so \
4 -v ${PWD}/../../trace/nd-trace:/usr/bin/nd-trace \
5 -v ${PWD}/1.php:/1.php \
6 -v ${PWD}/1:/1 \
7 --rm \
8 --namespace nd-test \
9 ninedogs \
10 bash /1
11
File test/php-container/exec-dev.sh added (mode: 100755) (index 0000000..49c1c0c)
1 podman run -ti \
2 -v ${PWD}/../../agent/ninedogs.so:/usr/lib64/ninedogs.so \
3 -v ${PWD}/../../agent/ninedogs_dlsym_env.so:/usr/lib64/ninedogs_dlsym_env.so \
4 -v ${PWD}/../../trace/nd-trace:/usr/bin/nd-trace \
5 -v ${PWD}/1.php:/1.php \
6 -v ${PWD}/1:/1 \
7 --rm \
8 --namespace nd-test \
9 ninedogs \
10 bash
11
File test/php-container/exec.sh added (mode: 100755) (index 0000000..99adeee)
1 podman run -ti --rm ninedogs \
2 -e LD_PRELOAD=/usr/lib64/ninedogs.so \
3 bash
File test/php-mysql/1.php added (mode: 100644) (index 0000000..87c66ad)
1 <?php
2 error_reporting(E_ALL);
3
4 echo 'Setting some tags...' . "\n";
5 file_put_contents('/dev/ninedogs', 'bla');
6
7 // TODO: running without ninedogs does not give a fatal error!
8 //try {
9 // echo 'Connecting with no params...' . "\n";
10 // $db = mysqli_connect(); // seems I cannot catch the fatal error! Should we?
11 //} catch (Exception $e) {}
12
13 try {
14 echo 'Connect to an invalid host using mysqli_connect...' . "\n";
15 $db = mysqli_connect('r1', 'user', 'pass', 'db', 33006, FALSE);
16 } catch (Exception $e) {}
17
18 echo 'Connecting 4 times to see the persistent allocation' . "\n";
19 for ($i = 0; $i < 4; $i++) {
20 $db = mysqli_init();
21 mysqli_real_connect($db, 'r1', 'ninedogs', 'pass', 'ninedogs', 3306,
22 FALSE, MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT);
23 }
24
25
26 echo 'Setting char set...' . "\n";
27 mysqli_set_charset($db, 'utf8mb4');
28
29
30 try {
31 echo 'Dropping non-existing table1...' . "\n";
32 $res = @mysqli_query($db, 'DROP TABLE non_existing1');
33 mysqli_free_result($res);
34 } catch (Exception $e) {}
35
36 if (1) {
37 echo 'Dropping table...' . "\n";
38 mysqli_query($db, 'DROP TABLE IF EXISTS n1');
39
40 echo 'Creating table...' . "\n";
41 mysqli_query($db, 'CREATE TABLE n1 (id INT, a1 TEXT, a2 TEXT, d NUMERIC)');
42
43 echo 'Inserting...' . "\n";
44 mysqli_query($db, 'INSERT INTO n1 (id, a1, a2, d)'
45 . ' VALUES (1, \'a1\', \'b1\', 8.1), (2, \'a2\', \'b2\', 8.2)');
46
47 // query without '$db'
48 $res = mysqli_query($db, 'SELECT id FROM n1 LIMIT 1');
49 $rows = mysqli_fetch_all($res);
50 mysqli_free_result($res);
51 }
52
53 if (1) {
54 echo 'Getting execution plan...' . "\n";
55 $sql = 'EXPLAIN EXTENDED'
56 . ' SELECT A.id, B.d FROM n1 A, n1 B WHERE A.id = B.id AND A.a1 = \'a\'';
57 $res = mysqli_query($db, $sql);
58 $rows = mysqli_fetch_all($res);
59 print_r($rows);
60 mysqli_free_result($res);
61 }
62
63 // query with parameters
64 echo 'Querying with parameters...' . "\n";
65 $sql = 'SELECT id, a1 FROM n1 WHERE id = ? OR id = ? OR d = ? OR a1 = ? OR a1 = ?';
66 $stmt = mysqli_prepare($db, $sql);
67 mysqli_stmt_bind_param($stmt, 'iidss', $a, $b, $c, $d, $e);
68 $a = 1; $b = $a + 1; $c = 8.3; $d = 'bla'; $e = 'bla2';
69 mysqli_stmt_execute($stmt);
70 $res = mysqli_stmt_get_result($stmt);
71 echo 'Calling native mysqli_num_rows:' . "\n";
72 echo 'native num_rows: ' . mysqli_num_rows($res) . "\n";
73 echo 'fetching data...' . "\n";
74 $rows = mysqli_fetch_all($res);
75 print_r($rows);
76 mysqli_free_result($res);
77 mysqli_stmt_close($stmt);
78
79 if (0) {
80 // give server a chance to request the query hash
81 for ($i = 0; $i <= 7; $i++) {
82 $res = mysqli_query($db, 'SELECT * FROM n1 LIMIT 1');
83 $rows = mysqli_fetch_all($res);
84 mysqli_free_result($res);
85 echo 'Tempo (10s)...' . "\n";
86 sleep(10);
87 }
88 }
89
90 echo 'Done!' . "\n";
91 exit(10);
92
93
File test/php-mysql/1.run copied from file test/php-pg/1.run (similarity 78%) (mode: 100755) (index f037596..ca14455)
3 3 export LD_PRELOAD=../../agent/ninedogs.so export LD_PRELOAD=../../agent/ninedogs.so
4 4
5 5 export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
6 export NINEDOGS_SERVER_PORT=6000
6 export NINEDOGS_SERVER_PORT=36000
7 7 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556
8 8 export NINEDOGS_VERBOSE=41 export NINEDOGS_VERBOSE=41
9 9 export NINEDOGS_SYNC_FLUSH=1 export NINEDOGS_SYNC_FLUSH=1
 
... ... 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
19 php 1.php &>1.out &
20 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!}
20 21
File test/php-pg/1.run changed (mode: 100755) (index f037596..39c80e9)
3 3 export LD_PRELOAD=../../agent/ninedogs.so export LD_PRELOAD=../../agent/ninedogs.so
4 4
5 5 export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
6 export NINEDOGS_SERVER_PORT=6000
6 export NINEDOGS_SERVER_PORT=36000
7 7 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556
8 8 export NINEDOGS_VERBOSE=41 export NINEDOGS_VERBOSE=41
9 9 export NINEDOGS_SYNC_FLUSH=1 export NINEDOGS_SYNC_FLUSH=1
File test/php-pg/1.run.gdb changed (mode: 100644) (index c4f407c..d88616c)
1 1 set environment LD_PRELOAD=../../agent/ninedogs.so set environment LD_PRELOAD=../../agent/ninedogs.so
2 2 set environment NINEDOGS_VERBOSE=40 set environment NINEDOGS_VERBOSE=40
3 3 set environment NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro set environment NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
4 set environment NINEDOGS_SERVER_PORT=6000
4 set environment NINEDOGS_SERVER_PORT=36000
5 5 set environment NINEDOGS_ID=ba446a981b387e831db3f6a730c55bc3 set environment NINEDOGS_ID=ba446a981b387e831db3f6a730c55bc3
6 6 set environment NINEDOGS_SYNC_FLUSH=1 set environment NINEDOGS_SYNC_FLUSH=1
7 7 set args 1.php set args 1.php
File test/python/redis1.py added (mode: 100644) (index 0000000..3fdf32f)
1 import redis
2
3 r = redis.Redis(host = 'r1', port = 6379, db = 0)
4 r.set('bla', 'bla-value')
5 print(r.get('bla'))
6
File test/python/redis1.run copied from file test/php-pg/1.run (similarity 52%) (mode: 100755) (index f037596..c00c847)
3 3 export LD_PRELOAD=../../agent/ninedogs.so export LD_PRELOAD=../../agent/ninedogs.so
4 4
5 5 export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
6 export NINEDOGS_SERVER_PORT=6000
6 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
12 export LD_DEBUG_OUTPUT=1.ld.txt
12 export LD_DEBUG_OUTPUT=redis1.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 \
19 php 1.php
18 ltrace -s200 -f -tt -S -o redis1.ltrace \
19 python redis1.py 2>&1 | LD_PRELOAD= tee redis1.out
20
21 exit 0
22
23 python redis1.py &
24 LD_PRELOAD= ../../trace/nd-trace -o redis1.nd -p ${!}
20 25
File test/python/sqlite1.py added (mode: 100644) (index 0000000..7c895e2)
1 import sqlite3
2
3 try:
4 db = sqlite3.connect('sqlite1.db')
5 cursor = db.cursor()
6
7 print('Dropping table...')
8 cursor.execute("DROP TABLE IF EXISTS test1")
9
10 table = """ CREATE TABLE test1 (
11 bla VARCHAR(255)
12 ); """
13 cursor.execute(table)
14
15 query = 'INSERT INTO test1 VALUES (:val);'
16 cursor.execute(query, { "val": "first_value"})
17
18 db.commit()
19 #cursor.execute("COMMIT;")
20
21 query = 'SELECT * FROM test1;'
22 cursor.execute(query)
23 result = cursor.fetchall()
24 print('Result is {}'.format(result))
25
26 cursor.close()
27
28 except sqlite3.Error as error:
29 print('Error occured - ', error)
30
31 finally:
32 if db:
33 db.close()
34
File test/python/sqlite1.run copied from file test/php-pg/1.run (similarity 50%) (mode: 100755) (index f037596..a5d3fe4)
3 3 export LD_PRELOAD=../../agent/ninedogs.so export LD_PRELOAD=../../agent/ninedogs.so
4 4
5 5 export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
6 export NINEDOGS_SERVER_PORT=6000
6 export NINEDOGS_SERVER_PORT=36000
7 7 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556
8 export NINEDOGS_VERBOSE=41
8 export NINEDOGS_VERBOSE=441
9 9 export NINEDOGS_SYNC_FLUSH=1 export NINEDOGS_SYNC_FLUSH=1
10 10
11 11 #export LD_DEBUG=all #export LD_DEBUG=all
12 export LD_DEBUG_OUTPUT=1.ld.txt
12 export LD_DEBUG_OUTPUT=sqlite1.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 \
19 php 1.php
18 #ltrace -s200 -f -tt -S -o sqlite1.ltrace \
19 #python sqlite1.py 2>&1 | LD_PRELOAD= tee sqlite1.out
20 20
21 python sqlite1.py &>sqlite1.out &
22 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o sqlite1.nd -p ${!}
File test/rg/1.run changed (mode: 100755) (index 982f8f5..f3d8e52)
3 3 export LD_PRELOAD=../../agent/ninedogs.so export LD_PRELOAD=../../agent/ninedogs.so
4 4
5 5 export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
6 export NINEDOGS_SERVER_PORT=6000
6 export NINEDOGS_SERVER_PORT=36000
7 7 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55bc1 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55bc1
8 8
9 9 export NINEDOGS_VERBOSE=300 export NINEDOGS_VERBOSE=300
File test/segv1/1.run changed (mode: 100755) (index cf48358..0f5fd3e)
... ... make segv
7 7 export LD_PRELOAD=../../agent/ninedogs.so export LD_PRELOAD=../../agent/ninedogs.so
8 8
9 9 export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
10 export NINEDOGS_SERVER_PORT=6000
10 export NINEDOGS_SERVER_PORT=36000
11 11 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556 export NINEDOGS_ID=ba446a981b387e831db3f6a730c55556
12 12 export NINEDOGS_VERBOSE=41 export NINEDOGS_VERBOSE=41
13 13 export NINEDOGS_SYNC_FLUSH=1 export NINEDOGS_SYNC_FLUSH=1
File trace/TODO changed (mode: 100644) (index 46edcbc..0dfcde9)
1 == Urgent ==
1 2 [ ] All functions must have 'c' and 'r' [ ] All functions must have 'c' and 'r'
2 3 Exaple: close can take a lot of time! Exaple: close can take a lot of time!
3 4 Not all, but the ones which may wait. Not all, but the ones which may wait.
4 5 [ ] With multiple threads, we cannot the 'tail_new' mambo jambo! [ ] With multiple threads, we cannot the 'tail_new' mambo jambo!
6 [ ] After fork, only the parent sees "-stop"!
7 [ ]
8
9
10 == Non urgent ==
11 [ ] We need to respect UTF-8 in bin2hex_ascii
5 12 [ ] [ ]
File trace/nd-trace.c changed (mode: 100644) (index 8c2ffa7..03197de)
8 8 #include <sys/un.h> #include <sys/un.h>
9 9
10 10 #include <arpa/inet.h> #include <arpa/inet.h>
11 #include <dlfcn.h>
11 12 #include <errno.h> #include <errno.h>
12 13 #include <fcntl.h> #include <fcntl.h>
13 14 #include <getopt.h> #include <getopt.h>
 
... ... static void usage(void)
43 44 exit(1); exit(1);
44 45 } }
45 46
46 static FILE *out;
47 static char do_exit;
47 static FILE *out;
48 static unsigned int do_exit;
48 49
49 50 static uint8_t decode8(unsigned char *d, unsigned int *i) static uint8_t decode8(unsigned char *d, unsigned int *i)
50 51 { {
 
... ... static uint64_t decode64(unsigned char *d, unsigned int *i)
78 79 return be64toh(u); return be64toh(u);
79 80 } }
80 81
82 static uint8_t decode_bool(const char *prefix, char *out, size_t out_size,
83 unsigned char *d, unsigned int *i)
84 {
85 uint8_t v = d[*i]; *i = *i + 1;
86 snprintf(out, out_size, "%s%s", prefix, v == 0 ? "NOK" : "OK");
87 return v;
88 }
89
81 90 static char *decode_socket_domain(const int d) static char *decode_socket_domain(const int d)
82 91 { {
83 92 switch (d) { switch (d) {
 
... ... static socklen_t decode_sockaddr(char *out, unsigned char *d, unsigned int *i)
241 250 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &ss; struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &ss;
242 251 char addr6[40]; char addr6[40];
243 252 inet_ntop(ss.ss_family, &s6->sin6_addr, addr6, sizeof(addr6)); inet_ntop(ss.ss_family, &s6->sin6_addr, addr6, sizeof(addr6));
244 sprintf(out, "ipv6/%s/%hu/f%u/s%u",
253 sprintf(out, "ipv6/%s/%hu/flow=%u/scope=%u",
245 254 addr6, be16toh(s6->sin6_port), addr6, be16toh(s6->sin6_port),
246 255 be32toh(s6->sin6_flowinfo), be32toh(s6->sin6_scope_id)); be32toh(s6->sin6_flowinfo), be32toh(s6->sin6_scope_id));
247 256 break; break;
 
... ... static void decode_stat(char *out, unsigned out_size,
566 575 s.st_mtim.tv_sec, s.st_mtim.tv_nsec, s.st_ctim.tv_sec, s.st_ctim.tv_nsec); s.st_mtim.tv_sec, s.st_mtim.tv_nsec, s.st_ctim.tv_sec, s.st_ctim.tv_nsec);
567 576 } }
568 577
569 static void decode_func(unsigned char *d)
578 static void decode_string_array(char *out, size_t out_size,
579 unsigned char *d, unsigned int *i)
580 {
581 size_t rest = out_size;
582 char *add = "";
583
584 strcpy(out, "");
585
586 while (1) {
587 unsigned short len = decode16(d, i);
588 if (len == 0)
589 break;
590
591 char e[len * 4 + 1];
592 bin2hex_ascii(e, d + *i, len); *i = *i + len;
593
594 unsigned int e_len = strlen(e);
595 if (e_len + 2 > rest) // 2 for ', '
596 break;
597
598 strcat(out, add);
599 strcat(out, e);
600 add = ", ";
601 rest -= e_len + 2;
602 }
603 }
604
605 static int decode_sqlite3_ret(char *out, unsigned out_size,
606 unsigned char *d, unsigned int *i)
607 {
608 unsigned int ret = decode32(d, i);
609
610 switch (ret) {
611 case 0: snprintf(out, out_size, "OK"); break;
612 case 1: snprintf(out, out_size, "ERROR"); break;
613 case 2: snprintf(out, out_size, "INTERNAL"); break;
614 case 3: snprintf(out, out_size, "PERM"); break;
615 case 4: snprintf(out, out_size, "ABORT"); break;
616 case 5: snprintf(out, out_size, "BUSY"); break;
617 case 6: snprintf(out, out_size, "LOCKED"); break;
618 case 7: snprintf(out, out_size, "NOMEM"); break;
619 case 8: snprintf(out, out_size, "READONLY"); break;
620 case 9: snprintf(out, out_size, "INTERRUPT"); break;
621 case 10: snprintf(out, out_size, "IOERR"); break;
622 case 11: snprintf(out, out_size, "CORRUPT"); break;
623 case 12: snprintf(out, out_size, "NOTFOUND"); break;
624 case 13: snprintf(out, out_size, "FULL"); break;
625 case 14: snprintf(out, out_size, "CANTOPEN"); break;
626 case 15: snprintf(out, out_size, "PROTOCOL"); break;
627 case 16: snprintf(out, out_size, "EMPTY"); break;
628 case 17: snprintf(out, out_size, "SCHEMA"); break;
629 case 18: snprintf(out, out_size, "TOOBIG"); break;
630 case 19: snprintf(out, out_size, "CONSTRAINT"); break;
631 case 20: snprintf(out, out_size, "MISMATCH"); break;
632 case 21: snprintf(out, out_size, "MISUSE"); break;
633 case 22: snprintf(out, out_size, "NOLFS"); break;
634 case 23: snprintf(out, out_size, "AUTH"); break;
635 case 24: snprintf(out, out_size, "FORMAT"); break;
636 case 25: snprintf(out, out_size, "RANGE"); break;
637 case 26: snprintf(out, out_size, "NOTADB"); break;
638 case 27: snprintf(out, out_size, "NOTICE"); break;
639 case 28: snprintf(out, out_size, "WARNING"); break;
640 case 100: snprintf(out, out_size, "ROW"); break;
641 case 101: snprintf(out, out_size, "DONE"); break;
642 default: snprintf(out, out_size, "todo(%u)", ret);
643 }
644
645 return ret;
646 }
647
648 static int decode_mysql_real_connect_flags(char *out, unsigned out_size,
649 unsigned char *d, unsigned int *i)
650 {
651 int ret = decode32(d, i);
652
653 char *found_rows = ""; if (ret & 2) found_rows = "|FOUND_ROWS";
654 char *compress = ""; if (ret & 32) compress = "|COMPRESS";
655 char *dont_ver = ""; if (ret & 64) dont_ver = "|SSL_DONT_VERIFY_SERVER_CERT";
656 char *ignore_space = ""; if (ret & 256) ignore_space = "|IGNORE_SPACE";
657 char *interact = ""; if (ret & 1024) interact = "|INTERACTIVE";
658 char *ssl = ""; if (ret & 2048) ssl = "SSL";
659
660 snprintf(out, out_size, "%x%s%s%s%s%s%s",
661 ret, found_rows, compress, dont_ver,
662 ignore_space, interact, ssl);
663
664 return ret;
665 }
666
667 static int decode_dlopen_flags(char *out, size_t out_size,
668 unsigned char *d, unsigned int *i)
669 {
670 int ret = decode32(d, i);
671
672 char *lazy = ""; if (ret & RTLD_LAZY) lazy = "|LAZY";
673 char *now = ""; if (ret & RTLD_NOW) lazy = "|NOW";
674 char *global = ""; if (ret & RTLD_GLOBAL) global = "|GLOBAL";
675 char *local = ""; if (ret & RTLD_LOCAL) local = "|LOCAL";
676 char *nodel = ""; if (ret & RTLD_NODELETE) nodel = "|NODELETE";
677 char *noload = ""; if (ret & RTLD_NOLOAD) nodel = "|NOLOAD";
678 char *deep = ""; if (ret & RTLD_DEEPBIND) deep = "|DEEPBIND";
679
680 snprintf(out, out_size, "%s%s%s%s%s%s%s",
681 lazy, now, global, local, nodel, noload, deep);
682
683 return ret;
684 }
685
686 static void decode_func(const uint32_t parent, unsigned char *d)
570 687 { {
571 688 unsigned int i = 0; unsigned int i = 0;
572 unsigned short func_len;
689 unsigned short func_len, trace_depth;
573 690 char type, line[64000], rest[2000]; char type, line[64000], rest[2000];
574 691 uint64_t t; uint64_t t;
575 692
 
... ... static void decode_func(unsigned char *d)
577 694 rest[0] = '\0'; rest[0] = '\0';
578 695
579 696 t = decode64(d, &i); t = decode64(d, &i);
697 trace_depth = decode16(d, &i);
580 698 func_len = decode16(d, &i); func_len = decode16(d, &i);
581 699 char func[func_len * 4 + 1]; char func[func_len * 4 + 1];
582 700 bin2hex_ascii(func, d + i, func_len); i += func_len; bin2hex_ascii(func, d + i, func_len); i += func_len;
 
... ... static void decode_func(unsigned char *d)
591 709 if (strcmp(func, "-stop") == 0) { if (strcmp(func, "-stop") == 0) {
592 710 int ret = decode32(d, &i); int ret = decode32(d, &i);
593 711 sprintf(line, "() = %d", ret); sprintf(line, "() = %d", ret);
594 do_exit = 1;
712 if (pid == parent) do_exit++;
595 713 } else if (strcmp(func, "-segv") == 0) { } else if (strcmp(func, "-segv") == 0) {
596 714 int r = decode32(d, &i); int r = decode32(d, &i);
597 715 sprintf(line, ":"); sprintf(line, ":");
598 716 for (int j = 0; j < r; j++) { for (int j = 0; j < r; j++) {
599 717 unsigned char len = decode8(d, &i); unsigned char len = decode8(d, &i);
600 718 char l[len * 4 + 1]; char l[len * 4 + 1];
601 bin2hex(l, d + i, len); i += len;
719 bin2hex_ascii(l, d + i, len); i += len;
602 720 strcat(line, " "); strcat(line, " ");
603 721 strcat(line, l); strcat(line, l);
604 722 } }
605 do_exit = 1;
723 if (pid == parent) do_exit++;
606 724 } break; } break;
607 725
608 726 case 'a': case 'a':
 
... ... static void decode_func(unsigned char *d)
667 785 uint16_t len = decode16(d, &i); uint16_t len = decode16(d, &i);
668 786 char filename[len * 4 + 1]; char filename[len * 4 + 1];
669 787 bin2hex_ascii(filename, d + i, len); i += len; bin2hex_ascii(filename, d + i, len); i += len;
670 int flags = decode32(d, &i);
788 char flags[128];
789 decode_dlopen_flags(flags, sizeof(flags), d, &i);
671 790 if (type == 'r') if (type == 'r')
672 791 decode_ret_pointer(rest, sizeof(rest), d, &i); decode_ret_pointer(rest, sizeof(rest), d, &i);
673 sprintf(line, "('%s', 0x%x)%s", filename, flags, rest);
792 sprintf(line, "('%s', '%s')%s", filename, flags, rest);
674 793 } else if (strcmp(func, "dlclose") == 0) { } else if (strcmp(func, "dlclose") == 0) {
675 794 void *h = (void *) decode64(d, &i); void *h = (void *) decode64(d, &i);
676 if (type == 'r')
677 decode_ret_int(rest, sizeof(rest), d, &i);
795 decode_ret_int(rest, sizeof(rest), d, &i);
678 796 sprintf(line, "(%p)%s", h, rest); sprintf(line, "(%p)%s", h, rest);
679 797 } break; } break;
680 798
799 case 'e':
800 if (strcmp(func, "execve") == 0) {
801 char argv[4096], envp[4096];
802 uint16_t len = decode16(d, &i);
803 char pathname[len * 4 + 1];
804 bin2hex_ascii(pathname, d + i, len); i += len;
805 decode_string_array(argv, sizeof(argv), d, &i);
806 decode_string_array(envp, sizeof(envp), d, &i);
807 if (type == 'r')
808 decode_ret_pointer(rest, sizeof(rest), d, &i);
809 sprintf(line, "('%s', {%s}, {%s})%s",
810 pathname, argv, envp, rest);
811 } break;
812
681 813 case 'f': case 'f':
682 if ((strcmp(func, "fstatat") == 0)
814 if (strcmp(func, "fork") == 0) {
815 decode_ret_int(rest, sizeof(rest), d, &i);
816 sprintf(line, "()%s", rest);
817 } else if ((strcmp(func, "fstatat") == 0)
683 818 || (strcmp(func, "fstat64") == 0)) { || (strcmp(func, "fstat64") == 0)) {
684 819 char dirfd[32], sstat[512]; char dirfd[32], sstat[512];
685 820 decode_dirfd(dirfd, sizeof(dirfd), d, &i, ""); decode_dirfd(dirfd, sizeof(dirfd), d, &i, "");
 
... ... static void decode_func(unsigned char *d)
692 827 decode_ret_pointer(rest, sizeof(rest), d, &i); decode_ret_pointer(rest, sizeof(rest), d, &i);
693 828 sprintf(line, "(%s, '%s', {%s}, 0x%x)%s", sprintf(line, "(%s, '%s', {%s}, 0x%x)%s",
694 829 dirfd, pathname, sstat, flags, rest); dirfd, pathname, sstat, flags, rest);
695 } else if (strcmp(func, "dlclose") == 0) {
696 void *h = (void *) decode64(d, &i);
697 if (type == 'r')
698 decode_ret_int(rest, sizeof(rest), d, &i);
699 sprintf(line, "(%p)%s", h, rest);
700 830 } break; } break;
701 831
702 832 case 'g': case 'g':
 
... ... static void decode_func(unsigned char *d)
775 905 //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);
776 906 int sock = decode32(d, &i); int sock = decode32(d, &i);
777 907 int backlog = decode32(d, &i); int backlog = decode32(d, &i);
778 if (type == 'r')
779 decode_ret_int(rest, sizeof(rest), d, &i);
908 decode_ret_int(rest, sizeof(rest), d, &i);
780 909 sprintf(line, "(%d, %d)%s", sock, backlog, rest); sprintf(line, "(%d, %d)%s", sock, backlog, rest);
781 910 } break; } break;
782 911
912 case 'm':
913 if (strcmp(func, "mysqli_close") == 0) {
914 uint64_t link = decode64(d, &i);
915 if (type == 'r')
916 decode_bool(" = ", rest, sizeof(rest), d, &i);
917 sprintf(line, "(link=0x%lx)%s", link, rest);
918 } else if (strcmp(func, "mysqli_connect") == 0) {
919 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
920 uint32_t cs_len = decode32(d, &i);
921 char cs[cs_len * 4 + 1];
922 bin2hex_ascii(cs, d + i, cs_len); i += cs_len;
923 if (type == 'r')
924 decode_bool(" = ", rest, sizeof(rest), d, &i);
925 sprintf(line, "('%s')%s", cs, rest);
926 } else if (strcmp(func, "mysqli_query") == 0) {
927 uint64_t link = decode64(d, &i);
928 uint16_t q_len = decode16(d, &i);
929 char q[q_len * 4 + 1];
930 bin2hex_ascii(q, d + i, q_len); i += q_len;
931 if (type == 'r') {
932 uint64_t res = decode64(d, &i);
933 if (res == 0)
934 snprintf(rest, sizeof(rest), " = nok");
935 else if (res == 1)
936 snprintf(rest, sizeof(rest), " = ok");
937 else
938 snprintf(rest, sizeof(rest), " = 0x%lx", res);
939 }
940 sprintf(line, "(link=0x%lx, '%s')%s", link, q, rest);
941 } else if (strcmp(func, "mysqli_real_connect") == 0) {
942 uint64_t link = decode64(d, &i);
943 uint32_t cs_len = decode32(d, &i);
944 char cs[cs_len * 4 + 1];
945 bin2hex_ascii(cs, d + i, cs_len); i += cs_len;
946 char flags[512];
947 decode_mysql_real_connect_flags(flags, sizeof(flags), d, &i);
948 if (type == 'r')
949 decode_bool(" = ", rest, sizeof(rest), d, &i);
950 sprintf(line, "(link=0x%lx, '%s', flags='%s')%s", link, cs, flags, rest);
951 } break;
952
783 953 case 'n': case 'n':
784 954 if (strcmp(func, "nanosleep") == 0) { if (strcmp(func, "nanosleep") == 0) {
785 955 struct timespec req; struct timespec req;
 
... ... static void decode_func(unsigned char *d)
799 969 } break; } break;
800 970
801 971 case 'o': case 'o':
802 if ((strcmp(func, "open") == 0) || (strcmp(func, "open64") == 0)
972 if ((strcmp(func, "open") == 0)
973 || (strcmp(func, "open64") == 0)
803 974 || (strcmp(func, "openat") == 0)) { || (strcmp(func, "openat") == 0)) {
804 975 char dirfd[32]; char dirfd[32];
805 976 if (strcmp(func, "openat") == 0) if (strcmp(func, "openat") == 0)
 
... ... static void decode_func(unsigned char *d)
807 978 else else
808 979 dirfd[0] = '\0'; dirfd[0] = '\0';
809 980 uint16_t len = decode16(d, &i); uint16_t len = decode16(d, &i);
810 char filename[len * 4 + 1];
811 bin2hex_ascii(filename, d + i, len); i += len;
981 char pathname[len * 4 + 1];
982 bin2hex_ascii(pathname, d + i, len); i += len;
812 983 int flags = decode32(d, &i); int flags = decode32(d, &i);
813 984 mode_t mode = decode32(d, &i); mode_t mode = decode32(d, &i);
814 985 if (type == 'r') if (type == 'r')
815 986 decode_ret_int(rest, sizeof(rest), d, &i); decode_ret_int(rest, sizeof(rest), d, &i);
816 sprintf(line, "('%s'%s, 0x%x, 0x%x)%s",
817 dirfd, filename, flags, mode, rest);
987 sprintf(line, "(%s'%s', 0x%x, 0x%x)%s",
988 dirfd, pathname, flags, mode, rest);
818 989 } break; } break;
819 990
820 991 case 'p': case 'p':
 
... ... static void decode_func(unsigned char *d)
839 1010 decode_ret_int(rest, sizeof(rest), d, &i); decode_ret_int(rest, sizeof(rest), d, &i);
840 1011 sprintf(line, "([%s], %u, %d)%s", sprintf(line, "([%s], %u, %d)%s",
841 1012 list, nf, timeout, rest); list, nf, timeout, rest);
1013 } 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 uint64_t h = decode64(d, &i);
1016 sprintf(line, "(0x%lx)", h);
1017 } else if ((strcmp(func, "pg_connect") == 0)
1018 || (strcmp(func, "pg_pconnect") == 0)) {
1019 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1020 uint32_t cs_len = decode32(d, &i);
1021 char cs[cs_len * 4 + 1];
1022 bin2hex_ascii(cs, d + i, cs_len); i += cs_len;
1023 if (type == 'r') {
1024 uint64_t h = decode64(d, &i);
1025 snprintf(rest, sizeof(rest), " = 0x%lx", h);
1026 }
1027 sprintf(line, "('%s')%s", cs, rest);
1028 } else if (strcmp(func, "pg_free_result") == 0) {
1029 void *res = (void *) decode64(d, &i);
1030 uint8_t ret = decode8(d, &i);
1031 sprintf(line, "(%p) = %s", res, ret == 1 ? "ok" : "nok");
1032 } else if ((strcmp(func, "pg_query") == 0)
1033 || (strcmp(func, "pg_query_params") == 0)
1034 || (strcmp(func, "pg_send_query") == 0)
1035 || (strcmp(func, "pg_send_query_params") == 0)) {
1036 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1037 uint64_t dbh = decode64(d, &i);
1038 uint16_t q_len = decode16(d, &i);
1039 char q[q_len * 4 + 1];
1040 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') {
1077 uint64_t res = decode64(d, &i);
1078 uint64_t rows = decode64(d, &i);
1079 uint64_t aff = decode64(d, &i);
1080 if (res == 1) // pg_send_query[_params]
1081 snprintf(rest, sizeof(rest),
1082 " = ok [%lu rows, %lu aff]",
1083 rows, aff);
1084 else if (res == 0) // pg_send_query[_params] TODO when this happens? pg_query returns false
1085 snprintf(rest, sizeof(rest), " = nok"); // TODO: error code
1086 else
1087 snprintf(rest, sizeof(rest),
1088 " = 0x%lx [%lu rows, %lu aff]",
1089 res, rows, aff);
1090 }
1091 sprintf(line, "(h=0x%lx, '%s')%s", dbh, q, rest);
1092 } else if (strcmp(func, "pg_get_result") == 0) {
1093 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1094 uint64_t dbh = decode64(d, &i);
1095 if (type == 'r') {
1096 uint64_t res = decode64(d, &i);
1097 uint64_t rows = decode64(d, &i);
1098 uint64_t aff = decode64(d, &i);
1099 snprintf(rest, sizeof(rest), " = 0x%lx [%lu rows, %lu aff]",
1100 res, rows, aff);
1101 }
1102 sprintf(line, "(h=0x%lx)%s", dbh, rest);
842 1103 } break; } break;
843 1104
844 1105 case 'r': case 'r':
 
... ... static void decode_func(unsigned char *d)
862 1123 sprintf(line, "(%d)%s", sock, rest); sprintf(line, "(%d)%s", sock, rest);
863 1124 } }
864 1125 } }
1126 } else if (strcmp(func, "recvfrom") == 0) {
1127 int sock = decode32(d, &i);
1128 uint64_t len = decode64(d, &i);
1129 int addrlen = decode32(d, &i);
1130 int flags = decode32(d, &i);
1131 if (type == 'c')
1132 sprintf(line, "(%d, buf, %zu, 0x%x, addr, %u)",
1133 sock, len, flags, addrlen);
1134 while (type == 'r') {
1135 ssize_t ret = decode_ret_int64(rest, sizeof(rest), d, &i);
1136 if (ret <= 0)
1137 break;
1138 uint16_t max = decode16(d, &i);
1139 char buf[max * 4 + 1];
1140 bin2hex_ascii(buf, d + i, max); i += max;
1141 if (addrlen == 0)
1142 break;
1143 char addr[addrlen * 2 + 1];
1144 bin2hex(addr, d + i, addrlen); i += addrlen; // TODO: we need to decode this!
1145 sprintf(line, "(%d, '%s'%s, %zd, 0x%x, '%s')%s",
1146 sock, buf, len > max ? "..." : "",
1147 len, flags, addr, rest);
1148 break;
1149 }
865 1150 } break; } break;
866 1151
867 1152 case 's': case 's':
 
... ... static void decode_func(unsigned char *d)
923 1208 int xdomain = decode32(d, &i); int xdomain = decode32(d, &i);
924 1209 int xtype = decode32(d, &i); int xtype = decode32(d, &i);
925 1210 int xprotocol = decode32(d, &i); int xprotocol = decode32(d, &i);
926 if (type == 'r')
927 decode_ret_int(rest, sizeof(rest), d, &i);
1211 decode_ret_int(rest, sizeof(rest), d, &i);
928 1212 sprintf(line, "(%s, %s, %d)%s", sprintf(line, "(%s, %s, %d)%s",
929 1213 decode_socket_domain(xdomain), decode_socket_domain(xdomain),
930 1214 decode_socket_type(xtype), xprotocol, rest); decode_socket_type(xtype), xprotocol, rest);
1215 } else if (strcmp(func, "sqlite3_open_v2") == 0) {
1216 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1217 uint16_t filename_len = decode16(d, &i);
1218 char filename[filename_len * 4 + 1];
1219 bin2hex_ascii(filename, d + i, filename_len); i += filename_len;
1220 int flags = decode32(d, &i);
1221 uint16_t vfs_len = decode16(d, &i);
1222 char vfs[vfs_len * 4 + 1];
1223 bin2hex_ascii(vfs, d + i, vfs_len); i += vfs_len;
1224
1225 if (type == 'c') {
1226 sprintf(line, "('%s', 0x%x, '%s')",
1227 filename, flags, vfs);
1228 } else {
1229 char err[64];
1230 int ret = decode_sqlite3_ret(err, sizeof(err), d, &i);
1231 uint64_t pdb = 0;
1232 if (ret == 0)
1233 pdb = decode64(d, &i);
1234 sprintf(line, "('%s', 0x%lx, 0x%x, '%s') = %s",
1235 filename, pdb, flags, vfs, err);
1236 }
1237 } else if (strcmp(func, "sqlite3_prepare_v2") == 0) {
1238 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1239 uint64_t h = decode64(d, &i);
1240 uint32_t sql_len = decode32(d, &i);
1241 char sql[sql_len * 4 + 1];
1242 bin2hex_ascii(sql, d + i, sql_len); i += sql_len;
1243 int nByte = decode32(d, &i);
1244 if (type == 'c') {
1245 sprintf(line, "(0x%lx, '%s', %d, stmt, tail)",
1246 h, sql, nByte);
1247 } else {
1248 uint64_t stmt = decode64(d, &i);
1249 char err[64];
1250 decode_sqlite3_ret(err, sizeof(err), d, &i);
1251 sprintf(line, "(0x%lx, '%s', %d, 0x%lx, tail) = %s",
1252 h, sql, nByte, stmt, err);
1253 }
1254 } else if (strcmp(func, "sqlite3_step") == 0) {
1255 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1256 uint64_t stmt = decode64(d, &i);
1257 if (type == 'c') {
1258 sprintf(line, "(0x%lx)", stmt);
1259 } else {
1260 char err[64];
1261 decode_sqlite3_ret(err, sizeof(err), d, &i);
1262 sprintf(line, "(0x%lx) = %s", stmt, err);
1263 }
931 1264 } else if (strcmp(func, "stat") == 0) { } else if (strcmp(func, "stat") == 0) {
932 1265 uint16_t len = decode16(d, &i); uint16_t len = decode16(d, &i);
933 1266 char pathname[len * 4 + 1]; char pathname[len * 4 + 1];
 
... ... static void decode_func(unsigned char *d)
985 1318 return; return;
986 1319 } }
987 1320
1321 char space[4096];
1322 unsigned short max = sizeof(space) - 1;
1323 if (max > trace_depth)
1324 max = trace_depth;
1325 memset(space, ' ', max);
1326 space[max] = '\0';
1327
988 1328 if (pid == tid) if (pid == tid)
989 fprintf(out, "%lu.%03lu %10u %s%s\n",
990 t / 1000, t % 1000, pid, func, line);
1329 fprintf(out, "%lu.%03lu %10u%s %s%s\n",
1330 t / 1000, t % 1000, pid, space, func, line);
991 1331 else else
992 fprintf(out, "%lu.%03lu %10u %10u %s%s\n",
993 t / 1000, t % 1000, pid, tid, func, line);
1332 fprintf(out, "%lu.%03lu %10u %10u%s %s%s\n",
1333 t / 1000, t % 1000, pid, tid, space, func, line);
994 1334 } }
995 1335
996 static void decode(unsigned char *d, size_t len)
1336 static void decode(const pid_t parent, unsigned char *d, size_t len)
997 1337 { {
998 1338 unsigned int i = 0; unsigned int i = 0;
999 1339 char type; char type;
1000 1340
1001 1341 type = d[i++]; type = d[i++];
1002 1342 if (type == 'F') { if (type == 'F') {
1003 decode_func(d + i);
1343 decode_func(parent, d + i);
1004 1344 } else { } else {
1005 1345 fprintf(out, "I do not know how to decode type [%c]!\n", type); fprintf(out, "I do not know how to decode type [%c]!\n", type);
1006 1346 char dump[len * 4 + 1]; char dump[len * 4 + 1];
 
... ... int main(int argc, char *argv[])
1016 1356 char *out_file = NULL; char *out_file = NULL;
1017 1357 pid_t pids[256]; pid_t pids[256];
1018 1358 int sm[256]; int sm[256];
1359 char version[256];
1019 1360 struct shared *shared[256]; struct shared *shared[256];
1020 1361 unsigned int no_pids = 0; unsigned int no_pids = 0;
1021 1362
1363 for (unsigned i = 0; i < 256; i++) {
1364 sm[i] = -2;
1365 version[i] = 0;
1366 }
1367
1022 1368 setlinebuf(stderr); setlinebuf(stderr);
1023 1369
1024 1370 while ((c = getopt_long(argc, argv, "p:o:", options, &options_index)) != -1) { while ((c = getopt_long(argc, argv, "p:o:", options, &options_index)) != -1) {
 
... ... int main(int argc, char *argv[])
1048 1394
1049 1395 //pid_t my_pid = getpid(); //pid_t my_pid = getpid();
1050 1396
1397 again:
1051 1398 for (unsigned i = 0; i < no_pids; i++) { for (unsigned i = 0; i < no_pids; i++) {
1399 if (sm[i] >= 0)
1400 continue;
1401
1052 1402 char name[128]; char name[128];
1053 1403 snprintf(name, sizeof(name), "/ninedogs-%d", pids[i]); snprintf(name, sizeof(name), "/ninedogs-%d", pids[i]);
1054 1404
1055 1405 sm[i] = shm_open(name, O_RDWR, 0); sm[i] = shm_open(name, O_RDWR, 0);
1056 1406 if (sm[i] == -1) { if (sm[i] == -1) {
1057 fprintf(stderr, "Cannot do shm_open i%u pid %d: %m\n", i, pids[i]);
1058 return 1;
1407 //fprintf(stderr, "%u: Cannot do shm_open: %m\n", pids[i]);
1408 continue;
1059 1409 } }
1060 fprintf(stderr, "shm_open i%u = %d\n", i, sm[i]);
1410 fprintf(stderr, "%u: shm_open returned %d\n", pids[i], sm[i]);
1061 1411
1062 1412 shared[i] = mmap(NULL, sizeof(struct shared), shared[i] = mmap(NULL, sizeof(struct shared),
1063 1413 PROT_READ | PROT_WRITE, MAP_SHARED, sm[i], 0); PROT_READ | PROT_WRITE, MAP_SHARED, sm[i], 0);
1064 1414 if (shared[i] == MAP_FAILED) { if (shared[i] == MAP_FAILED) {
1065 fprintf(stderr, "Cannot mmap i%u: %m\n", i);
1066 return 1;
1415 //fprintf(stderr, "Cannot mmap i%u: %m\n", i);
1416 close(sm[i]);
1417 sm[i] = -1;
1418 continue;
1067 1419 } }
1068 1420
1421 fprintf(stderr, "%u: Attached\n", pids[i]);
1422
1069 1423 #if 0 #if 0
1070 1424 unsigned j = 0; unsigned j = 0;
1071 1425 shared[i]->buf[j++] = SHARED_CMD_INIT; shared[i]->buf[j++] = SHARED_CMD_INIT;
 
... ... int main(int argc, char *argv[])
1075 1429
1076 1430 r = sem_post(&shared[i]->sem1); r = sem_post(&shared[i]->sem1);
1077 1431 if (r == -1) { if (r == -1) {
1078 fprintf(stderr, "Cannot post sem1: %m\n");
1432 fprintf(stderr, "%u: Cannot post sem1: %m\n", pids[i]);
1079 1433 return 1; return 1;
1080 1434 } }
1081 1435 #endif #endif
1082 1436 } }
1083 1437
1084 while (1) {
1085 1438 for (unsigned i = 0; i < no_pids; i++) { for (unsigned i = 0; i < no_pids; i++) {
1086 1439 unsigned char *p; unsigned char *p;
1087 1440 unsigned int ava; unsigned int ava;
1088 1441 unsigned char buf[64000]; unsigned char buf[64000];
1089 1442 struct stat s; struct stat s;
1090 1443
1091 if (do_exit) {
1444 if (do_exit == no_pids) {
1092 1445 fprintf(stderr, "Bye!\n"); fprintf(stderr, "Bye!\n");
1093 1446 break; break;
1094 1447 } }
1095 1448
1096 1449 fstat(sm[i], &s); fstat(sm[i], &s);
1097 1450 if (s.st_size == 0) { if (s.st_size == 0) {
1098 fprintf(out, "size[%u](fd %d)=%ld\n", i, sm[i], s.st_size);
1451 //fprintf(out, "%u: Shared memory size is zero!\n", pids[i]);
1099 1452 continue; continue;
1100 1453 } }
1454 //fprintf(out, "%u: Shared memory size: %ld\n", pids[i], s.st_size);
1101 1455
1102 1456 r = sem_wait(&shared[i]->sem1); r = sem_wait(&shared[i]->sem1);
1103 1457 if (r == -1) { if (r == -1) {
1104 fprintf(stderr, "Cannot wait for sem1: %m\n");
1458 fprintf(stderr, "%u: Cannot wait for sem1: %m\n", pids[i]);
1105 1459 return 1; return 1;
1106 1460 } }
1107 1461
1108 1462 r = sem_post(&shared[i]->sem1); r = sem_post(&shared[i]->sem1);
1109 1463 if (r == -1) { if (r == -1) {
1110 fprintf(stderr, "Cannot post sem1: %m\n");
1464 fprintf(stderr, "%u: Cannot post sem1: %m\n", pids[i]);
1111 1465 return 1; return 1;
1112 1466 } }
1113 1467
1468 if (version[i] == 0) {
1469 version[i] = shared[i]->version;
1470 fprintf(out, "%u: version is %hhu\n", pids[i], version[i]);
1471 }
1472
1114 1473 // tail-1 points to last value available // tail-1 points to last value available
1115 1474 if (shared[i]->tail == shared[i]->head) if (shared[i]->tail == shared[i]->head)
1116 1475 continue; continue;
 
... ... while (1) {
1139 1498 plen = be16toh(plen); plen = be16toh(plen);
1140 1499 } }
1141 1500 if (plen > ava) { if (plen > ava) {
1142 fprintf(out, " Too short packet: plen=%hu > ava[%u]!\n",
1143 plen, ava);
1501 fprintf(out, "%u: Too short packet: plen=%hu > ava[%u]!\n",
1502 pids[i], plen, ava);
1144 1503 break; break;
1145 1504 } }
1146 1505
 
... ... while (1) {
1160 1519 if (0) { if (0) {
1161 1520 char dump[plen * 4 + 1]; char dump[plen * 4 + 1];
1162 1521 bin2hex_ascii(dump, p, plen); bin2hex_ascii(dump, p, plen);
1163 fprintf(out, " DUMP[%hu] head=%u: %s\n", plen, shared[i]->head, dump);
1522 fprintf(out, "%u: DUMP[%hu] head=%u: %s\n",
1523 pids[i], plen, shared[i]->head, dump);
1164 1524 } }
1165 1525
1166 decode(p + 2, plen - 2);
1526 decode(pids[i], p + 2, plen - 2);
1167 1527
1168 1528 shared[i]->head = (shared[i]->head + plen) % shared[i]->buf_size; shared[i]->head = (shared[i]->head + plen) % shared[i]->buf_size;
1169 1529 ava -= plen; ava -= plen;
 
... ... while (1) {
1171 1531 } }
1172 1532 } }
1173 1533
1174 if (do_exit)
1175 break;
1176 }
1534 if (!do_exit)
1535 goto again;
1536
1177 1537 // TODO: print some stats // TODO: print some stats
1178 1538 return 0; return 0;
1179 1539 } }
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