server.probe.bpf.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. // Copyright The OpenTelemetry Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "arguments.h"
  15. #include "span_context.h"
  16. #include "go_context.h"
  17. #include "go_types.h"
  18. #include "uprobe.h"
  19. //char __license[] SEC("license") = "Dual MIT/GPL";
  20. #define PATH_MAX_LEN 128
  21. #define MAX_BUCKETS 8
  22. #define METHOD_MAX_LEN 8
  23. #define MAX_CONCURRENT 50
  24. #define REMOTE_ADDR_MAX_LEN 256
  25. #define HOST_MAX_LEN 256
  26. #define PROTO_MAX_LEN 8
  27. struct http_server_span_t {
  28. BASE_SPAN_PROPERTIES
  29. u64 status_code;
  30. char method[METHOD_MAX_LEN];
  31. char path[PATH_MAX_LEN];
  32. char remote_addr[REMOTE_ADDR_MAX_LEN];
  33. char host[HOST_MAX_LEN];
  34. char proto[PROTO_MAX_LEN];
  35. };
  36. struct uprobe_data_t {
  37. struct http_server_span_t span;
  38. // bpf2go doesn't support pointers fields
  39. // saving the response pointer in the entry probe
  40. // and using it in the return probe
  41. u64 resp_ptr;
  42. };
  43. struct {
  44. __uint(type, BPF_MAP_TYPE_HASH);
  45. __type(key, void *);
  46. __type(value, struct uprobe_data_t);
  47. __uint(max_entries, MAX_CONCURRENT);
  48. } http_server_uprobes SEC(".maps");
  49. struct {
  50. __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  51. __uint(key_size, sizeof(u32));
  52. __uint(value_size, sizeof(struct map_bucket));
  53. __uint(max_entries, MAX_CONCURRENT);
  54. } golang_mapbucket_storage_map SEC(".maps");
  55. struct {
  56. __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  57. __uint(key_size, sizeof(u32));
  58. __uint(value_size, sizeof(struct cw_header_token));
  59. __uint(max_entries, MAX_CONCURRENT);
  60. } header_range SEC(".maps");
  61. struct {
  62. __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  63. __uint(key_size, sizeof(u32));
  64. __uint(value_size, sizeof(struct span_context));
  65. __uint(max_entries, 1);
  66. } parent_span_context_storage_map SEC(".maps");
  67. struct {
  68. __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  69. __uint(key_size, sizeof(u32));
  70. __uint(value_size, sizeof(struct apm_span_context));
  71. __uint(max_entries, 1);
  72. } cw_parent_span_context_storage_map SEC(".maps");
  73. struct {
  74. __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  75. __uint(key_size, sizeof(u32));
  76. __uint(value_size, sizeof(struct uprobe_data_t));
  77. __uint(max_entries, 1);
  78. } http_server_uprobe_storage_map SEC(".maps");
  79. struct {
  80. __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
  81. } events SEC(".maps");
  82. struct header_key {
  83. char str[CW_HEADER_KEY_LENGTH];
  84. };
  85. struct {
  86. __uint(type, BPF_MAP_TYPE_HASH);
  87. __uint(key_size, sizeof(u32));
  88. __uint(value_size, sizeof(struct header_key));
  89. __uint(max_entries, 8);
  90. } header_keys_map SEC(".maps");
  91. struct {
  92. __uint(type, BPF_MAP_TYPE_LRU_HASH);
  93. __uint(key_size, sizeof(u64));
  94. __uint(value_size, sizeof(char [CW_HEADER_VAL_LENGTH]));
  95. __uint(max_entries, MAX_CONCURRENT);
  96. } http_server_context_headers SEC(".maps");
  97. // Injected in init
  98. // volatile const u64 ctx_ptr_pos;
  99. // volatile const u64 headers_ptr_pos;
  100. // volatile const u64 buckets_ptr_pos;
  101. //for (int i = 0; i < W3C_KEY_LENGTH; i++)
  102. //{
  103. //if (current_header_key[i] != "traceparent"[i]){
  104. //goto outer_loop;
  105. //}
  106. //if (current_header_key[i] != "Traceparent"[i]){
  107. //goto outer_loop;
  108. //}
  109. //}
  110. static __always_inline struct span_context *extract_context_from_req_headers_del(void *headers_ptr_ptr) {
  111. void *headers_ptr;
  112. long res;
  113. res = bpf_probe_read(&headers_ptr, sizeof(headers_ptr), headers_ptr_ptr);
  114. if (res < 0) {
  115. return NULL;
  116. }
  117. u64 headers_count = 0;
  118. res = bpf_probe_read(&headers_count, sizeof(headers_count), headers_ptr);
  119. if (res < 0) {
  120. return NULL;
  121. }
  122. if (headers_count == 0) {
  123. return NULL;
  124. }
  125. unsigned char log_2_bucket_count;
  126. res = bpf_probe_read(&log_2_bucket_count, sizeof(log_2_bucket_count), headers_ptr + 9);
  127. if (res < 0) {
  128. return NULL;
  129. }
  130. u64 bucket_count = 1 << log_2_bucket_count;
  131. __u64 pid_tgid = bpf_get_current_pid_tgid();
  132. __u32 tgid = pid_tgid >> 32;
  133. struct ebpf_proc_info *proc_info =
  134. bpf_map_lookup_elem(&proc_info_map, &tgid);
  135. if(!proc_info)
  136. {
  137. return 0;
  138. }
  139. // Check if Go version >= 1.24 (Swiss Tables)
  140. if (proc_info->version >= GO_VERSION(1, 24, 0)) {
  141. // Swiss Tables uses dirPtr instead of buckets, structure is incompatible
  142. // Skip header reading for Go 1.24+
  143. return NULL;
  144. }
  145. void *header_buckets;
  146. res = bpf_probe_read(&header_buckets, sizeof(header_buckets), (void *) (headers_ptr + proc_info->buckets_ptr_pos));
  147. if (res < 0) {
  148. return NULL;
  149. }
  150. u32 map_id = 0;
  151. struct map_bucket *map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
  152. if (!map_value) {
  153. return NULL;
  154. }
  155. for (u32 j = 0; j < MAX_BUCKETS; j++) {
  156. if (j >= bucket_count) {
  157. break;
  158. }
  159. res = bpf_probe_read(map_value, sizeof(struct map_bucket), header_buckets + (j * sizeof(struct map_bucket)));
  160. if (res < 0) {
  161. continue;
  162. }
  163. // for (u32 i = 0; i < 8; i++) {
  164. u32 i = 0;
  165. if (map_value->tophash[i] != 0 && map_value->keys[i].len == CW_HEADER_KEY_LENGTH) {
  166. // char current_header_key[CW_HEADER_KEY_LENGTH];
  167. // bpf_probe_read(current_header_key, sizeof(current_header_key), map_value->keys[i].str);
  168. for (int ii = 0; ii < CW_HEADER_KEY_LENGTH; ii++) {
  169. if (map_value->keys[i].str[ii] != CW_HEADER_KEY_VAL[i] && map_value->keys[i].str[ii] != CW_HEADER_KEY_UFIRST_VAL[ii]) {
  170. // goto outer_loop;
  171. }
  172. }
  173. // continue;
  174. }
  175. // if (map_value->keys[i].len != CW_HEADER_KEY_LENGTH) {
  176. // continue;
  177. // }
  178. // char current_header_key[CW_HEADER_KEY_LENGTH];
  179. // bpf_probe_read(current_header_key, sizeof(current_header_key), map_value->keys[i].str);
  180. //
  181. // struct header_key * current_header_key = bpf_map_lookup_elem(&header_keys_map, &map_id);
  182. // if (current_header_key) {
  183. // bpf_probe_read(current_header_key->str, sizeof(current_header_key->str), map_value->keys[i].str);
  184. // }
  185. //
  186. // for (int i = 0; i < CW_HEADER_KEY_LENGTH; i++) {
  187. // if (current_header_key[i] != CW_HEADER_KEY_VAL[i] && current_header_key[i] != CW_HEADER_KEY_UFIRST_VAL[i]) {
  188. // goto outer_loop;
  189. // }
  190. // }
  191. //
  192. // void *traceparent_header_value_ptr = map_value->values[i].array;
  193. // struct go_string_ot traceparent_header_value_go_str;
  194. // res = bpf_probe_read(&traceparent_header_value_go_str, sizeof(traceparent_header_value_go_str),
  195. // traceparent_header_value_ptr);
  196. // // 00-95b5ec2b81e2374a4a27ce36ab71d349-18f65a5a3ab22213-02
  197. // cw_bpf_debug("traceparent_header_value_go_str.str:%s", traceparent_header_value_go_str.str);
  198. //
  199. // if (res < 0) {
  200. // return NULL;
  201. // }
  202. //
  203. // // char traceparent_header_value[130];
  204. // int key = 0;
  205. // char *traceparent_header_value;
  206. // traceparent_header_value = bpf_map_lookup_elem(&go_large_array_map, &key);
  207. //
  208. // res = bpf_probe_read(&traceparent_header_value, sizeof(traceparent_header_value),
  209. // traceparent_header_value_go_str.str);
  210. //
  211. //
  212. // if (res < 0) {
  213. // return NULL;
  214. // }
  215. // struct span_context *parent_span_context = bpf_map_lookup_elem(&parent_span_context_storage_map, &map_id);
  216. // if (!parent_span_context) {
  217. // cw_bpf_debug("no parent_span_context");
  218. // return NULL;
  219. // }
  220. // struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&cw_parent_span_context_storage_map, &map_id);
  221. // if (!cw_parent_span_context) {
  222. // cw_bpf_debug("no cw_parent_span_context");
  223. // return NULL;
  224. // }
  225. //
  226. // w3c_string_to_span_context(traceparent_header_value, parent_span_context);
  227. //
  228. // cw_string_to_span_context(traceparent_header_value, cw_parent_span_context);
  229. //
  230. // // 保存sc
  231. // cw_save_parent_tracking_span(cw_parent_span_context);
  232. //
  233. // return parent_span_context;
  234. // outer_loop:
  235. // continue;
  236. // }
  237. }
  238. return NULL;
  239. }
  240. // 获取 get_map_bucket
  241. static __always_inline struct map_bucket *get_map_bucket(void *headers_ptr_ptr) {
  242. void *headers_ptr;
  243. long res;
  244. res = bpf_probe_read(&headers_ptr, sizeof(headers_ptr), headers_ptr_ptr);
  245. if (res < 0) {
  246. return NULL;
  247. }
  248. u64 headers_count = 0;
  249. res = bpf_probe_read(&headers_count, sizeof(headers_count), headers_ptr);
  250. if (res < 0) {
  251. return NULL;
  252. }
  253. if (headers_count == 0) {
  254. return NULL;
  255. }
  256. unsigned char log_2_bucket_count;
  257. res = bpf_probe_read(&log_2_bucket_count, sizeof(log_2_bucket_count), headers_ptr + 9);
  258. if (res < 0) {
  259. return NULL;
  260. }
  261. u64 bucket_count = 1 << log_2_bucket_count;
  262. __u64 pid_tgid = bpf_get_current_pid_tgid();
  263. __u32 tgid = pid_tgid >> 32;
  264. struct ebpf_proc_info *proc_info =
  265. bpf_map_lookup_elem(&proc_info_map, &tgid);
  266. if(!proc_info)
  267. {
  268. return NULL;
  269. }
  270. void *header_buckets;
  271. res = bpf_probe_read(&header_buckets, sizeof(header_buckets), (void *) (headers_ptr + proc_info->buckets_ptr_pos));
  272. if (res < 0) {
  273. return NULL;
  274. }
  275. u32 map_id = 0;
  276. struct map_bucket *map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
  277. if (!map_value) {
  278. return NULL;
  279. }
  280. __builtin_memset(map_value, 0, sizeof(struct map_bucket));
  281. for (u32 j = 0; j < 8; j++) {
  282. if (j >= bucket_count) {
  283. break;
  284. }
  285. res = bpf_probe_read(map_value, sizeof(struct map_bucket), header_buckets + (j * sizeof(struct map_bucket)));
  286. if (res == 0) {
  287. return map_value;
  288. }
  289. }
  290. return NULL;
  291. }
  292. MAP_BUCKET_DEFINITION(go_string_ot, go_slice_ot)
  293. static __always_inline char *
  294. extract_context_from_req_headers_pre_parsed(void *key) {
  295. char *header_val =
  296. bpf_map_lookup_elem(&http_server_context_headers, &key);
  297. if (!header_val) {
  298. return NULL;
  299. }
  300. return header_val;
  301. }
  302. static __always_inline char *extract_context_from_req_headers_go_map(void *headers_ptr_ptr)
  303. {
  304. void *headers_ptr;
  305. long res;
  306. res = bpf_probe_read(&headers_ptr, sizeof(headers_ptr), headers_ptr_ptr);
  307. if (res < 0)
  308. {
  309. return NULL;
  310. }
  311. u64 headers_count = 0;
  312. res = bpf_probe_read(&headers_count, sizeof(headers_count), headers_ptr);
  313. if (res < 0)
  314. {
  315. return NULL;
  316. }
  317. if (headers_count == 0)
  318. {
  319. return NULL;
  320. }
  321. unsigned char log_2_bucket_count;
  322. res = bpf_probe_read(&log_2_bucket_count, sizeof(log_2_bucket_count), headers_ptr + 9);
  323. if (res < 0)
  324. {
  325. return NULL;
  326. }
  327. u64 bucket_count = 1 << log_2_bucket_count;
  328. void *header_buckets;
  329. /**/
  330. __u64 pid_tgid = bpf_get_current_pid_tgid();
  331. __u32 tgid = pid_tgid >> 32;
  332. struct ebpf_proc_info *proc_info =
  333. bpf_map_lookup_elem(&proc_info_map, &tgid);
  334. if(!proc_info)
  335. {
  336. return NULL;
  337. }
  338. /**/
  339. res = bpf_probe_read(&header_buckets, sizeof(header_buckets), (void*)(headers_ptr + proc_info->buckets_ptr_pos));
  340. if (res < 0)
  341. {
  342. return NULL;
  343. }
  344. u32 map_id = 0;
  345. MAP_BUCKET_TYPE(go_string_ot, go_slice_ot) *map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
  346. if (!map_value)
  347. {
  348. return NULL;
  349. }
  350. for (u64 j = 0; j < MAX_BUCKETS; j++)
  351. {
  352. if (j >= bucket_count)
  353. {
  354. break;
  355. }
  356. res = bpf_probe_read(map_value, sizeof(MAP_BUCKET_TYPE(go_string_ot, go_slice_ot)), header_buckets + (j * sizeof(MAP_BUCKET_TYPE(go_string_ot, go_slice_ot))));
  357. if (res < 0)
  358. {
  359. continue;
  360. }
  361. for (u64 i = 0; i < 8; i++)
  362. {
  363. if (map_value->tophash[i] == 0)
  364. {
  365. continue;
  366. }
  367. if (map_value->keys[i].len != CW_HEADER_KEY_LENGTH)
  368. {
  369. continue;
  370. }
  371. char current_header_key[CW_HEADER_KEY_LENGTH];
  372. bpf_probe_read(current_header_key, sizeof(current_header_key), map_value->keys[i].str);
  373. if (!bpf_memcmp(current_header_key, CW_HEADER_KEY_VAL, CW_HEADER_KEY_LENGTH) && !bpf_memcmp(current_header_key, CW_HEADER_KEY_UFIRST_VAL, CW_HEADER_KEY_LENGTH))
  374. {
  375. continue;
  376. }
  377. void *traceparent_header_value_ptr = map_value->values[i].array;
  378. struct go_string_ot traceparent_header_value_go_str;
  379. res = bpf_probe_read(&traceparent_header_value_go_str, sizeof(traceparent_header_value_go_str), traceparent_header_value_ptr);
  380. if (res < 0)
  381. {
  382. return NULL;
  383. }
  384. if (traceparent_header_value_go_str.len != CW_HEADER_VAL_LENGTH)
  385. {
  386. continue;
  387. }
  388. char traceparent_header_value2[CW_HEADER_VAL_LENGTH];
  389. res = bpf_probe_read(&traceparent_header_value2, sizeof(traceparent_header_value2), traceparent_header_value_go_str.str);
  390. if (res < 0)
  391. {
  392. return NULL;
  393. }
  394. // bpf_printk("has cw header111 j=%d i=%d %s", j, i,traceparent_header_value_go_str.str);
  395. return traceparent_header_value_go_str.str;
  396. // w3c_string_to_span_context(traceparent_header_value, parent_span_context);
  397. // return 0;
  398. }
  399. }
  400. return NULL;
  401. }
  402. static __always_inline char *
  403. extract_context_from_req_headers(void *key, void *headers_ptr_ptr, __u64 use_swiss) {
  404. if (use_swiss == 1) {
  405. return extract_context_from_req_headers_pre_parsed(key);
  406. }
  407. return extract_context_from_req_headers_go_map(headers_ptr_ptr);
  408. }
  409. // 获取 header_val
  410. static __always_inline char *get_header_val(struct map_bucket *map_value,u32 off,u32 count) {
  411. for (u32 i = off; i < count; i++) {
  412. if (map_value->tophash[i] != 0 && map_value->keys[i].len == CW_HEADER_KEY_LENGTH) {
  413. char current_header_key[CW_HEADER_KEY_LENGTH];
  414. bpf_probe_read(current_header_key, sizeof(current_header_key), map_value->keys[i].str);
  415. if ((current_header_key[0] == CW_HEADER_KEY_VAL[0]
  416. || current_header_key[0] == CW_HEADER_KEY_UFIRST_VAL[0])
  417. && current_header_key[1] == CW_HEADER_KEY_UFIRST_VAL[1]
  418. && current_header_key[2] == CW_HEADER_KEY_UFIRST_VAL[2]
  419. && current_header_key[3] == CW_HEADER_KEY_UFIRST_VAL[3]
  420. && current_header_key[4] == CW_HEADER_KEY_UFIRST_VAL[4]
  421. && current_header_key[5] == CW_HEADER_KEY_UFIRST_VAL[5]
  422. && current_header_key[6] == CW_HEADER_KEY_UFIRST_VAL[6]) {
  423. void *traceparent_header_value_ptr = map_value->values[i].array;
  424. struct go_string_ot traceparent_header_value_go_str;
  425. long res = bpf_probe_read(&traceparent_header_value_go_str, sizeof(traceparent_header_value_go_str),
  426. traceparent_header_value_ptr);
  427. if (res == 0) {
  428. cw_bpf_debug("get_header_val %d-%d %s",off,count,traceparent_header_value_go_str.str);
  429. return traceparent_header_value_go_str.str;
  430. }
  431. }
  432. }
  433. }
  434. return NULL;
  435. }
  436. // 分段获取 header_val
  437. static __always_inline char *get_header_val_off(struct map_bucket *map_value) {
  438. char *val = get_header_val(map_value, 0, 2);
  439. if (val == NULL) {
  440. val = get_header_val(map_value, 2, 4);
  441. }
  442. if (val == NULL) {
  443. val = get_header_val(map_value, 4, 6);
  444. }
  445. if (val == NULL) {
  446. val = get_header_val(map_value, 6, 8);
  447. }
  448. return val;
  449. }
  450. // This instrumentation attaches uprobe to the following function:
  451. // func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)
  452. SEC("uprobe/HandlerFunc_ServeHTTP")
  453. int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) {
  454. cw_bpf_debug("[uprobe_HandlerFunc_ServeHTTP]");
  455. __u64 pid_tgid = bpf_get_current_pid_tgid();
  456. __u32 tgid = pid_tgid >> 32;
  457. struct ebpf_proc_info *proc_info =
  458. bpf_map_lookup_elem(&proc_info_map, &tgid);
  459. if(!proc_info)
  460. {
  461. cw_bpf_debug("[uprobe_HandlerFunc_ServeHTTP] no proc info");
  462. return 0;
  463. }
  464. void *req_ctx_ptr = get_Go_context(ctx, 4, proc_info->ctx_ptr_pos, false);
  465. void *key = get_consistent_key(ctx, req_ctx_ptr);
  466. void *httpReq_ptr = bpf_map_lookup_elem(&http_server_uprobes, &key);
  467. if (httpReq_ptr != NULL) {
  468. cw_bpf_debug("uprobe/HandlerFunc_ServeHTTP already tracked with the current request");
  469. return 0;
  470. }
  471. u32 map_id = 0;
  472. struct uprobe_data_t *uprobe_data = bpf_map_lookup_elem(&http_server_uprobe_storage_map, &map_id);
  473. if (uprobe_data == NULL) {
  474. cw_bpf_debug("uprobe/HandlerFunc_ServeHTTP: http_server_span is NULL");
  475. return 0;
  476. }
  477. __builtin_memset(uprobe_data, 0, sizeof(struct uprobe_data_t));
  478. // Save response writer
  479. void *resp_impl = get_argument(ctx, 3);
  480. uprobe_data->resp_ptr = (u64) resp_impl;
  481. struct http_server_span_t *http_server_span = &uprobe_data->span;
  482. http_server_span->start_time = bpf_ktime_get_ns();
  483. // return 1;
  484. // Propagate context
  485. void *req_ptr = get_argument(ctx, 4);
  486. // struct map_bucket * map_bucket_p = get_map_bucket((void *) (req_ptr + proc_info->headers_ptr_pos));
  487. char *traceparent_header_value = extract_context_from_req_headers(key,
  488. (void *) (req_ptr + proc_info->headers_ptr_pos),
  489. proc_info->use_swiss_map);
  490. // bpf_printk("111 %s",traceparent_header_value);
  491. // char * traceparent_header_value = get_header_val_off(map_bucket_p);
  492. struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&cw_parent_span_context_storage_map, &map_id);
  493. if (!cw_parent_span_context) {
  494. return 0;
  495. }
  496. __builtin_memset(cw_parent_span_context, 0, sizeof(struct apm_span_context));
  497. if (traceparent_header_value != NULL) {
  498. cw_bpf_debug("traceparent_header_value != NULL");
  499. cw_string_to_span_context(traceparent_header_value, cw_parent_span_context);
  500. // found parent context in http headers
  501. // http_server_span->psc = *parent_ctx;
  502. // copy traceID
  503. copy_byte_arrays(http_server_span->psc.TraceID, http_server_span->sc.TraceID, TRACE_ID_SIZE);
  504. // 生成随机SpanID
  505. generate_random_bytes(http_server_span->sc.SpanID, SPAN_ID_SIZE);
  506. cw_save_parent_tracking_span(cw_parent_span_context);
  507. } else {
  508. cw_bpf_debug("traceparent_header_value == NULL");
  509. http_server_span->sc = generate_span_context();
  510. struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&cw_parent_span_context_storage_map, &map_id);
  511. if (!cw_parent_span_context) {
  512. return 0;
  513. }
  514. // struct apm_span_context context = {};
  515. generate_random_bytes(cw_parent_span_context->trace_id, TRACE_ID_SIZE);
  516. // generate_random_bytes(context.span_id, SPAN_ID_SIZE);
  517. // 保存 trace_id 到psc
  518. cw_save_parent_tracking_span(cw_parent_span_context);
  519. }
  520. if (req_ctx_ptr == NULL) {
  521. // cw_bpf_debug("uprobe/HandlerFunc_ServeHTTP: req_ctx_ptr is NULL");
  522. return 0;
  523. }
  524. // cw_bpf_debug("found parent context in http headers");
  525. // cw_bpf_debug("parent_span_context-TraceID---");
  526. // for (int i = 0; i < TRACE_ID_SIZE; i++) {
  527. // cw_bpf_debug("%02x", uprobe_data->span.sc.TraceID[i]);
  528. // }
  529. // cw_bpf_debug("parent_span_context-SpanID---");
  530. // for (int i = 0; i < SPAN_ID_SIZE; i++) {
  531. // cw_bpf_debug("%02x", uprobe_data->span.sc.SpanID[i]);
  532. // }
  533. // bpf_map_update_elem(&http_server_uprobes, &key, uprobe_data, 0);
  534. // start_tracking_span(req_ctx_ptr, &http_server_span->sc);
  535. // void save_tracking_span(struct apm_span_context *sc)
  536. return 0;
  537. }
  538. // This instrumentation attaches uprobe to the following function:
  539. // func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)
  540. SEC("uprobe/HandlerFunc_ServeHTTP")
  541. int uprobe_HandlerFunc_ServeHTTP_Returns(struct pt_regs *ctx) {
  542. // return 1;
  543. cw_bpf_debug("[uprobe_HandlerFunc_ServeHTTP_Returns]");
  544. // u64 end_time = bpf_ktime_get_ns();
  545. __u64 pid_tgid = bpf_get_current_pid_tgid();
  546. __u32 tgid = pid_tgid >> 32;
  547. struct ebpf_proc_info *proc_info =
  548. bpf_map_lookup_elem(&proc_info_map, &tgid);
  549. if(!proc_info)
  550. {
  551. return 0;
  552. }
  553. void *req_ctx_ptr = get_Go_context(ctx, 4, proc_info->ctx_ptr_pos, false);
  554. void *key = get_consistent_key(ctx, req_ctx_ptr);
  555. struct uprobe_data_t *uprobe_data = bpf_map_lookup_elem(&http_server_uprobes, &key);
  556. if (uprobe_data == NULL) {
  557. cw_bpf_debug("uprobe/HandlerFunc_ServeHTTP_Returns: entry_state is NULL");
  558. bpf_map_delete_elem(&http_server_context_headers, &key);
  559. return 0;
  560. }
  561. bpf_map_delete_elem(&http_server_uprobes, &key);
  562. bpf_map_delete_elem(&http_server_context_headers, &key);
  563. struct http_server_span_t *http_server_span = &uprobe_data->span;
  564. // void *resp_ptr = (void *) uprobe_data->resp_ptr;
  565. // void *req_ptr = NULL;
  566. // bpf_probe_read(&req_ptr, sizeof(req_ptr), (void *) (resp_ptr + req_ptr_pos));
  567. // http_server_span->end_time = end_time;
  568. //
  569. // void *url_ptr = 0;
  570. // bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *) (req_ptr + url_ptr_pos));
  571. // // Collect fields from response
  572. // read_go_string(req_ptr, method_ptr_pos, http_server_span->method, sizeof(http_server_span->method),
  573. // "method from request");
  574. // read_go_string(url_ptr, path_ptr_pos, http_server_span->path, sizeof(http_server_span->path),
  575. // "path from Request.URL");
  576. // read_go_string(req_ptr, remote_addr_pos, http_server_span->remote_addr, sizeof(http_server_span->remote_addr),
  577. // "remote addr from Request.RemoteAddr");
  578. // read_go_string(req_ptr, host_pos, http_server_span->host, sizeof(http_server_span->host), "host from Request.Host");
  579. // read_go_string(req_ptr, proto_pos, http_server_span->proto, sizeof(http_server_span->proto),
  580. // "proto from Request.Proto");
  581. //
  582. // // status code
  583. // bpf_probe_read(&http_server_span->status_code, sizeof(http_server_span->status_code),
  584. // (void *) (resp_ptr + status_code_pos));
  585. //
  586. // bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, http_server_span, sizeof(*http_server_span));
  587. stop_tracking_span(&http_server_span->sc, &http_server_span->psc);
  588. clear_parent_span_context();
  589. cw_bpf_debug("HTTP_END");
  590. return 0;
  591. }
  592. // This instrumentation attaches uprobe to the following function:
  593. // func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) {
  594. SEC("uprobe/textproto_Reader_readContinuedLineSlice")
  595. int uprobe_textproto_Reader_readContinuedLineSlice_Returns(struct pt_regs *ctx) {
  596. void *key = (void *) GOROUTINE(ctx);
  597. u64 len = (u64) GO_PARAM2(ctx);
  598. u8 *buf = (u8 *) GO_PARAM1(ctx);
  599. if (len == (CW_HEADER_KEY_LENGTH + CW_HEADER_VAL_LENGTH + 2)) {
  600. long cw_header_native = 0x3A65636172747763LL; // 小端序下的 "cwtrace:"
  601. __u64 key64 = 0;
  602. bpf_probe_read_user(&key64, sizeof(key64), buf);
  603. if (key64 == cw_header_native) {
  604. char header_val[CW_HEADER_VAL_LENGTH] = {};
  605. bpf_probe_read_user(header_val, sizeof(header_val), buf + CW_HEADER_KEY_LENGTH + 2);
  606. cw_bpf_debug("Swiss Map:%s", header_val);
  607. bpf_map_update_elem(&http_server_context_headers, &key, &header_val, BPF_ANY);
  608. }
  609. }
  610. return 0;
  611. }