|
|
@@ -48,6 +48,27 @@ struct
|
|
|
__uint(max_entries, 1);
|
|
|
} http_client_uprobe_storage_map SEC(".maps");
|
|
|
|
|
|
+
|
|
|
+struct {
|
|
|
+ __uint(type, BPF_MAP_TYPE_LRU_HASH);
|
|
|
+ __type(key, void*); // the headers ptr
|
|
|
+ __type(value, void*); // request key, goroutine or context ptr
|
|
|
+ __uint(max_entries, MAX_CONCURRENT);
|
|
|
+} http_headers SEC(".maps");
|
|
|
+
|
|
|
+struct cw_header_storage {
|
|
|
+ char tp[CW_HEADER_VAL_LENGTH];
|
|
|
+ char tp_str[CW_HEADER_KEY_LENGTH + 2 + CW_HEADER_VAL_LENGTH + 2];
|
|
|
+ char end[2];
|
|
|
+};
|
|
|
+
|
|
|
+struct {
|
|
|
+ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
|
|
|
+ __uint(key_size, sizeof(u32));
|
|
|
+ __uint(value_size, sizeof(struct cw_header_storage));
|
|
|
+ __uint(max_entries, 1);
|
|
|
+} cw_header_storage_map SEC(".maps");
|
|
|
+
|
|
|
//struct {
|
|
|
// __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
|
|
//} events SEC(".maps");
|
|
|
@@ -63,345 +84,7 @@ struct
|
|
|
// volatile const u64 request_host_pos;
|
|
|
// volatile const u64 request_proto_pos;
|
|
|
|
|
|
-static __always_inline long inject_header(void* headers_ptr, struct span_context* propagated_ctx) {
|
|
|
- bpf_printk("11111111111111");
|
|
|
- // Read the key-value count - this field must be the first one in the hmap struct as documented in src/runtime/map.go
|
|
|
- u64 curr_keyvalue_count = 0;
|
|
|
- long res = bpf_probe_read_user(&curr_keyvalue_count, sizeof(curr_keyvalue_count), headers_ptr);
|
|
|
-
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Couldn't read map key-value count from user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- if (curr_keyvalue_count >= 8) {
|
|
|
- cw_bpf_debug("Map size is bigger than 8, skipping context propagation");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // Get pointer to temp bucket struct we store in a map (avoiding large local variable on the stack)
|
|
|
- // Performing read-modify-write on the bucket
|
|
|
- u32 map_id = 1;
|
|
|
- struct map_bucket *bucket_map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
|
|
|
- if (!bucket_map_value) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- __builtin_memset(bucket_map_value, 0, sizeof(struct map_bucket));
|
|
|
-
|
|
|
- __u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
- __u32 tgid = pid_tgid >> 32;
|
|
|
- struct ebpf_proc_info *proc_info =
|
|
|
- bpf_map_lookup_elem(&proc_info_map, &tgid);
|
|
|
- if(!proc_info)
|
|
|
- {
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- void *buckets_ptr_ptr = (void*) (headers_ptr + proc_info->buckets_ptr_pos);
|
|
|
- void *bucket_ptr = 0; // The actual pointer to the buckets
|
|
|
-
|
|
|
- if (curr_keyvalue_count == 0) {
|
|
|
- bpf_printk("curr_keyvalue_count == 0");
|
|
|
-
|
|
|
- // No key-value pairs in the Go map, need to "allocate" memory for the user
|
|
|
- bucket_ptr = write_target_data(bucket_map_value, sizeof(struct map_bucket));
|
|
|
- if (bucket_ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write bucket to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- // Update the buckets pointer in the hmap struct to point to newly allocated bucket
|
|
|
- res = bpf_probe_write_user(buckets_ptr_ptr, &bucket_ptr, sizeof(bucket_ptr));
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Failed to update the map bucket pointer for the user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- } else {
|
|
|
- // There is at least 1 key-value pair, hence the bucket pointer from the user is valid
|
|
|
- // Read the bucket pointer
|
|
|
- res = bpf_probe_read_user(&bucket_ptr, sizeof(bucket_ptr), buckets_ptr_ptr);
|
|
|
- // Read the user's bucket to the eBPF map entry
|
|
|
- bpf_probe_read_user(bucket_map_value, sizeof(struct map_bucket), bucket_ptr);
|
|
|
- }
|
|
|
-
|
|
|
- u8 bucket_index = curr_keyvalue_count & 0x7;
|
|
|
- bpf_printk("bucket_index:%d",bucket_index);
|
|
|
-
|
|
|
- char traceparent_tophash = 0xee;
|
|
|
- bucket_map_value->tophash[bucket_index] = traceparent_tophash;
|
|
|
-
|
|
|
- // Prepare the key string for the user
|
|
|
- char key[W3C_KEY_LENGTH] = "traceparent";
|
|
|
- void *ptr = write_target_data(key, W3C_KEY_LENGTH);
|
|
|
- if (ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write key to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- bucket_map_value->keys[bucket_index] = (struct go_string_ot) {.len = W3C_KEY_LENGTH, .str = ptr};
|
|
|
-
|
|
|
- // Prepare the value string slice
|
|
|
- // First the value string which constains the span context
|
|
|
- char val[W3C_VAL_LENGTH];
|
|
|
- span_context_to_w3c_string(propagated_ctx, val);
|
|
|
- ptr = write_target_data(val, sizeof(val));
|
|
|
- if(ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write value to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // The go string pointing to the above val
|
|
|
- struct go_string_ot header_value = {.len = W3C_VAL_LENGTH, .str = ptr};
|
|
|
- ptr = write_target_data((void*)&header_value, sizeof(header_value));
|
|
|
- if(ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write go_string to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // Last, go_slice pointing to the above go_string
|
|
|
- bucket_map_value->values[bucket_index] = (struct go_slice_ot) {.array = ptr, .cap = 1, .len = 1};
|
|
|
-
|
|
|
- // Update the map header count field
|
|
|
- curr_keyvalue_count += 1;
|
|
|
- res = bpf_probe_write_user(headers_ptr, &curr_keyvalue_count, sizeof(curr_keyvalue_count));
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Failed to update key-value count in map header");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // Update the bucket
|
|
|
- res = bpf_probe_write_user(bucket_ptr, bucket_map_value, sizeof(struct map_bucket));
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Failed to update bucket content");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- bpf_memset((unsigned char *)bucket_map_value, sizeof(struct map_bucket), 0);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-// 00:00:1015481350055581:5450531005555981:5610250100539899:304775019cd3218a304775019cd3218a:1001025098564810:140acc88cde8773f
|
|
|
-static __always_inline long cw_inject_header(void* headers_ptr, struct apm_span_context* propagated_ctx) {
|
|
|
- // Read the key-value count - this field must be the first one in the hmap struct as documented in src/runtime/map.go
|
|
|
- u64 curr_keyvalue_count = 0;
|
|
|
- long res = bpf_probe_read_user(&curr_keyvalue_count, sizeof(curr_keyvalue_count), headers_ptr);
|
|
|
-
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Couldn't read map key-value count from user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- if (curr_keyvalue_count >= 8) {
|
|
|
- cw_bpf_debug("Map size is bigger than 8, skipping context propagation");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // Get pointer to temp bucket struct we store in a map (avoiding large local variable on the stack)
|
|
|
- // Performing read-modify-write on the bucket
|
|
|
- u32 map_id = 0;
|
|
|
- struct map_bucket *bucket_map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
|
|
|
- if (!bucket_map_value) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- __u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
- __u32 tgid = pid_tgid >> 32;
|
|
|
- struct ebpf_proc_info *proc_info =
|
|
|
- bpf_map_lookup_elem(&proc_info_map, &tgid);
|
|
|
- if(!proc_info)
|
|
|
- {
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- void *buckets_ptr_ptr = (void*) (headers_ptr + proc_info->buckets_ptr_pos);
|
|
|
- void *bucket_ptr = 0; // The actual pointer to the buckets
|
|
|
-
|
|
|
- if (curr_keyvalue_count == 0) {
|
|
|
- // No key-value pairs in the Go map, need to "allocate" memory for the user
|
|
|
- bucket_ptr = write_target_data(bucket_map_value, sizeof(struct map_bucket));
|
|
|
- if (bucket_ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write bucket to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- // Update the buckets pointer in the hmap struct to point to newly allocated bucket
|
|
|
- res = bpf_probe_write_user(buckets_ptr_ptr, &bucket_ptr, sizeof(bucket_ptr));
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Failed to update the map bucket pointer for the user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- } else {
|
|
|
- // There is at least 1 key-value pair, hence the bucket pointer from the user is valid
|
|
|
- // Read the bucket pointer
|
|
|
- res = bpf_probe_read_user(&bucket_ptr, sizeof(bucket_ptr), buckets_ptr_ptr);
|
|
|
- // Read the user's bucket to the eBPF map entry
|
|
|
- bpf_probe_read_user(bucket_map_value, sizeof(struct map_bucket), bucket_ptr);
|
|
|
- }
|
|
|
-
|
|
|
- u8 bucket_index = curr_keyvalue_count & 0x7;
|
|
|
-
|
|
|
- char traceparent_tophash = 0xee;
|
|
|
- bucket_map_value->tophash[bucket_index] = traceparent_tophash;
|
|
|
-
|
|
|
- // Prepare the key string for the user
|
|
|
- char key[W3C_KEY_LENGTH] = "traceparent";
|
|
|
- void *ptr = write_target_data(key, W3C_KEY_LENGTH);
|
|
|
- if (ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write key to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- bucket_map_value->keys[bucket_index] = (struct go_string_ot) {.len = W3C_KEY_LENGTH, .str = ptr};
|
|
|
-
|
|
|
- // Prepare the value string slice
|
|
|
- // First the value string which constains the span context
|
|
|
- char val[CW_HEADER_LENGTH];
|
|
|
- span_context_to_cw_string(propagated_ctx, val);
|
|
|
- ptr = write_target_data(val, sizeof(val));
|
|
|
- if(ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write value to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // The go string pointing to the above val
|
|
|
- struct go_string_ot header_value = {.len = CW_HEADER_LENGTH, .str = ptr};
|
|
|
- ptr = write_target_data((void*)&header_value, sizeof(header_value));
|
|
|
- if(ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write go_string to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // Last, go_slice pointing to the above go_string
|
|
|
- bucket_map_value->values[bucket_index] = (struct go_slice_ot) {.array = ptr, .cap = 1, .len = 1};
|
|
|
-
|
|
|
- // Update the map header count field
|
|
|
- curr_keyvalue_count += 1;
|
|
|
- res = bpf_probe_write_user(headers_ptr, &curr_keyvalue_count, sizeof(curr_keyvalue_count));
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Failed to update key-value count in map header");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // Update the bucket
|
|
|
- res = bpf_probe_write_user(bucket_ptr, bucket_map_value, sizeof(struct map_bucket));
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Failed to update bucket content");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- bpf_memset((unsigned char *)bucket_map_value, sizeof(struct map_bucket), 0);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-// 00:00:1015481350055581:5450531005555981:5610250100539899:304775019cd3218a304775019cd3218a:1001025098564810:140acc88cde8773f
|
|
|
-static __always_inline long cw_inject_header2(void* headers_ptr, struct apm_span_context* propagated_ctx) {
|
|
|
- // Read the key-value count - this field must be the first one in the hmap struct as documented in src/runtime/map.go
|
|
|
- u64 curr_keyvalue_count = 0;
|
|
|
- long res = bpf_probe_read_user(&curr_keyvalue_count, sizeof(curr_keyvalue_count), headers_ptr);
|
|
|
-
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Couldn't read map key-value count from user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- if (curr_keyvalue_count >= 8) {
|
|
|
- cw_bpf_debug("Map size is bigger than 8, skipping context propagation");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // Get pointer to temp bucket struct we store in a map (avoiding large local variable on the stack)
|
|
|
- // Performing read-modify-write on the bucket
|
|
|
- u32 map_id = 0;
|
|
|
- struct map_bucket *bucket_map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
|
|
|
- if (!bucket_map_value) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- __u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
- __u32 tgid = pid_tgid >> 32;
|
|
|
- struct ebpf_proc_info *proc_info =
|
|
|
- bpf_map_lookup_elem(&proc_info_map, &tgid);
|
|
|
- if(!proc_info)
|
|
|
- {
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- void *buckets_ptr_ptr = (void*) (headers_ptr + proc_info->buckets_ptr_pos);
|
|
|
- void *bucket_ptr = 0; // The actual pointer to the buckets
|
|
|
-
|
|
|
- if (curr_keyvalue_count == 0) {
|
|
|
- // No key-value pairs in the Go map, need to "allocate" memory for the user
|
|
|
- bucket_ptr = write_target_data(bucket_map_value, sizeof(struct map_bucket));
|
|
|
- if (bucket_ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write bucket to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- // Update the buckets pointer in the hmap struct to point to newly allocated bucket
|
|
|
- res = bpf_probe_write_user(buckets_ptr_ptr, &bucket_ptr, sizeof(bucket_ptr));
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Failed to update the map bucket pointer for the user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- } else {
|
|
|
- // There is at least 1 key-value pair, hence the bucket pointer from the user is valid
|
|
|
- // Read the bucket pointer
|
|
|
- res = bpf_probe_read_user(&bucket_ptr, sizeof(bucket_ptr), buckets_ptr_ptr);
|
|
|
- // Read the user's bucket to the eBPF map entry
|
|
|
- bpf_probe_read_user(bucket_map_value, sizeof(struct map_bucket), bucket_ptr);
|
|
|
- }
|
|
|
-
|
|
|
- u8 bucket_index = curr_keyvalue_count & 0x7;
|
|
|
-
|
|
|
-// char traceparent_tophash = 0xee;
|
|
|
-// bucket_map_value->tophash[bucket_index] = traceparent_tophash;
|
|
|
-
|
|
|
- // Prepare the key string for the user
|
|
|
- char key[CW_HEADER_KEY_LENGTH] = CW_HEADER_KEY_VAL;
|
|
|
- void *ptr = write_target_data(key, CW_HEADER_KEY_LENGTH);
|
|
|
- if (ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write key to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- bucket_map_value->keys[bucket_index] = (struct go_string_ot) {.len = CW_HEADER_KEY_LENGTH, .str = ptr};
|
|
|
-
|
|
|
- char traceparent_tophash = 0xee;
|
|
|
- bucket_map_value->tophash[bucket_index] = traceparent_tophash;
|
|
|
- bucket_map_value->keys[bucket_index] = (struct go_string_ot) {.len = CW_HEADER_KEY_LENGTH, .str = ptr};
|
|
|
-
|
|
|
-
|
|
|
- // Prepare the value string slice
|
|
|
- // First the value string which constains the span context
|
|
|
- char val[CW_HEADER_VAL_LENGTH];
|
|
|
- span_context_to_cw_string(propagated_ctx, val);
|
|
|
- ptr = write_target_data(val, sizeof(val));
|
|
|
- if(ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write value to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // The go string pointing to the above val
|
|
|
- struct go_string_ot header_value = {.len = CW_HEADER_VAL_LENGTH, .str = ptr};
|
|
|
- ptr = write_target_data((void*)&header_value, sizeof(header_value));
|
|
|
- if(ptr == NULL) {
|
|
|
- cw_bpf_debug("inject_header: Failed to write go_string to user");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // Last, go_slice pointing to the above go_string
|
|
|
- bucket_map_value->values[bucket_index] = (struct go_slice_ot) {.array = ptr, .cap = 1, .len = 1};
|
|
|
|
|
|
- // Update the map header count field
|
|
|
- curr_keyvalue_count += 1;
|
|
|
- res = bpf_probe_write_user(headers_ptr, &curr_keyvalue_count, sizeof(curr_keyvalue_count));
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Failed to update key-value count in map header");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // Update the bucket
|
|
|
- res = bpf_probe_write_user(bucket_ptr, bucket_map_value, sizeof(struct map_bucket));
|
|
|
- if (res < 0) {
|
|
|
- cw_bpf_debug("Failed to update bucket content");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- bpf_memset((unsigned char *)bucket_map_value, sizeof(struct map_bucket), 0);
|
|
|
- return 0;
|
|
|
-}
|
|
|
|
|
|
// 00:00:1015481350055581:5450531005555981:5610250100539899:304775019cd3218a304775019cd3218a:1001025098564810:140acc88cde8773f
|
|
|
static __always_inline long cw_inject_header_half(void* headers_ptr, char * header_str,struct ebpf_proc_info* proc_info) {
|
|
|
@@ -570,7 +253,9 @@ int uprobe_Transport_roundTrip(struct pt_regs *ctx) {
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
- void *key = get_consistent_key(ctx, context_ptr_val);
|
|
|
+ void *key = (void *)GOROUTINE(ctx);
|
|
|
+// cw_bpf_debug("[start]:%llu",key);
|
|
|
+
|
|
|
void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key);
|
|
|
if (httpReq_ptr != NULL)
|
|
|
{
|
|
|
@@ -682,6 +367,10 @@ int uprobe_Transport_roundTrip(struct pt_regs *ctx) {
|
|
|
// get headers from Request
|
|
|
void *headers_ptr = 0;
|
|
|
bpf_probe_read(&headers_ptr, sizeof(headers_ptr), (void *)(req_ptr+proc_info->headers_ptr_pos));
|
|
|
+ if (headers_ptr) {
|
|
|
+ bpf_map_update_elem(&http_headers, &headers_ptr, &key, 0);
|
|
|
+ }
|
|
|
+
|
|
|
// long res = inject_header(headers_ptr, &httpReq->sc);
|
|
|
// long res = cw_inject_header(headers_ptr, &httpReq->apm_sc);
|
|
|
// if (res < 0) {
|
|
|
@@ -690,16 +379,17 @@ int uprobe_Transport_roundTrip(struct pt_regs *ctx) {
|
|
|
char val[CW_HEADER_VAL_LENGTH];
|
|
|
span_context_to_cw_string(&httpReq->apm_sc, val);
|
|
|
|
|
|
- long res2 = cw_inject_header_half(headers_ptr, val,proc_info);
|
|
|
- if (res2 < 0) {
|
|
|
- cw_bpf_debug("uprobe_Transport_roundTrip: Failed to inject header");
|
|
|
- return -1;
|
|
|
- }
|
|
|
+// long res2 = cw_inject_header_half(headers_ptr, val,proc_info);
|
|
|
+// if (res2 < 0) {
|
|
|
+// cw_bpf_debug("uprobe_Transport_roundTrip: Failed to inject header");
|
|
|
+// return -1;
|
|
|
+// }
|
|
|
+
|
|
|
// Write event
|
|
|
bpf_map_update_elem(&http_events, &key, httpReq, 0);
|
|
|
start_tracking_span(context_ptr_val, &httpReq->sc);
|
|
|
|
|
|
- bpf_tail_call(ctx, &NAME(progs_jmp_up_map), PROG_DATA_GO_UPDATE_HEADER_UP_IDX);
|
|
|
+// bpf_tail_call(ctx, &NAME(progs_jmp_up_map), PROG_DATA_GO_UPDATE_HEADER_UP_IDX);
|
|
|
|
|
|
// bpf_tail_call(ctx, &jmp_table2, 0);
|
|
|
|
|
|
@@ -838,7 +528,8 @@ int uprobe_Transport_roundTrip_Returns(struct pt_regs *ctx) {
|
|
|
}
|
|
|
|
|
|
void *req_ctx_ptr = get_Go_context(ctx, 2, proc_info->ctx_ptr_pos, false);
|
|
|
- void *key = get_consistent_key(ctx, req_ctx_ptr);
|
|
|
+ void *key = (void *)GOROUTINE(ctx);
|
|
|
+// bpf_printk("[end]:%llu",key);
|
|
|
|
|
|
struct http_request_t *http_req_span = bpf_map_lookup_elem(&http_events, &key);
|
|
|
if (http_req_span == NULL) {
|
|
|
@@ -862,4 +553,79 @@ int uprobe_Transport_roundTrip_Returns(struct pt_regs *ctx) {
|
|
|
|
|
|
bpf_map_delete_elem(&http_events, &key);
|
|
|
return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+SEC("uprobe/header_writeSubset")
|
|
|
+int uprobe_writeSubset(struct pt_regs *ctx) {
|
|
|
+ u64 headers_pos = 1;
|
|
|
+ void *headers_ptr = get_argument(ctx, headers_pos);
|
|
|
+
|
|
|
+ u64 io_writer_pos = 3;
|
|
|
+ void *io_writer_ptr = get_argument(ctx, io_writer_pos);
|
|
|
+
|
|
|
+ __u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
+ __u32 tgid = pid_tgid >> 32;
|
|
|
+ struct ebpf_proc_info *proc_info = bpf_map_lookup_elem(&proc_info_map, &tgid);
|
|
|
+ if (!proc_info) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ void **key_ptr = bpf_map_lookup_elem(&http_headers, &headers_ptr);
|
|
|
+ if (key_ptr) {
|
|
|
+ void *key = *key_ptr;
|
|
|
+ struct http_request_t *http_req_span = bpf_map_lookup_elem(&http_events, &key);
|
|
|
+ cw_bpf_debug("[writeSubset]:%llu",key);
|
|
|
+ if (http_req_span) {
|
|
|
+ // Get storage from per-cpu array map instead of stack
|
|
|
+ u32 map_id = 0;
|
|
|
+ struct cw_header_storage *storage = bpf_map_lookup_elem(&cw_header_storage_map, &map_id);
|
|
|
+ if (!storage) {
|
|
|
+ cw_bpf_debug("uprobe_writeSubset: Failed to get storage from map");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ __builtin_memset(storage, 0, sizeof(struct cw_header_storage));
|
|
|
+ span_context_to_cw_string(&http_req_span->apm_sc, storage->tp);
|
|
|
+ void *buf_ptr = 0;
|
|
|
+ bpf_probe_read(&buf_ptr, sizeof(buf_ptr),
|
|
|
+ (void *) (io_writer_ptr + proc_info->io_writer_buf_ptr_pos)); // grab buf ptr
|
|
|
+ if (!buf_ptr) {
|
|
|
+ cw_bpf_debug("uprobe_writeSubset: Failed to get buf from io writer");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
+ s64 size = 0;
|
|
|
+ if (bpf_probe_read(&size, sizeof(s64), (void *) (io_writer_ptr + proc_info->io_writer_buf_ptr_pos +
|
|
|
+ offsetof(struct go_slice, cap)))) { // grab capacity
|
|
|
+ cw_bpf_debug("uprobe_writeSubset: Failed to get size from io writer");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
+ s64 len = 0;
|
|
|
+ if (bpf_probe_read(&len, sizeof(s64), (void *) (io_writer_ptr + proc_info->io_writer_n_pos))) { // grab len
|
|
|
+ cw_bpf_debug("uprobe_writeSubset: Failed to get len from io writer");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (len < (size - CW_HEADER_VAL_LENGTH - CW_HEADER_KEY_LENGTH - 4)) { // 4 = strlen(": ") + strlen("\r\n")
|
|
|
+ // Initialize tp_str with "cwtrace: "
|
|
|
+ __builtin_memcpy(storage->tp_str, "cwtrace: ", CW_HEADER_KEY_LENGTH + 2);
|
|
|
+ __builtin_memcpy(&storage->tp_str[CW_HEADER_KEY_LENGTH + 2], storage->tp, sizeof(storage->tp));
|
|
|
+ __builtin_memcpy(storage->end, "\r\n", 2);
|
|
|
+ __builtin_memcpy(&storage->tp_str[CW_HEADER_KEY_LENGTH + 2 + CW_HEADER_VAL_LENGTH], storage->end, sizeof(storage->end));
|
|
|
+ if (bpf_probe_write_user(buf_ptr + (len & 0x0ffff), storage->tp_str, sizeof(storage->tp_str))) {
|
|
|
+ cw_bpf_debug("uprobe_writeSubset: Failed to write trace parent key in buffer");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ len += CW_HEADER_KEY_LENGTH + 2 + CW_HEADER_VAL_LENGTH + 2;
|
|
|
+ if (bpf_probe_write_user((void *) (io_writer_ptr + proc_info->io_writer_n_pos), &len, sizeof(len))) {
|
|
|
+ cw_bpf_debug("uprobe_writeSubset: Failed to change io writer n");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ done:
|
|
|
+ bpf_map_delete_elem(&http_headers, &headers_ptr);
|
|
|
+ return 0;
|
|
|
}
|