hc
2023-12-09 958e46acc8e900e8569dd467c1af9b8d2d019394
kernel/tools/perf/util/thread.c
....@@ -1,36 +1,39 @@
11 // SPDX-License-Identifier: GPL-2.0
2
-#include "../perf.h"
32 #include <errno.h>
43 #include <stdlib.h>
54 #include <stdio.h>
65 #include <string.h>
76 #include <linux/kernel.h>
7
+#include <linux/zalloc.h>
8
+#include "dso.h"
89 #include "session.h"
910 #include "thread.h"
1011 #include "thread-stack.h"
11
-#include "util.h"
1212 #include "debug.h"
1313 #include "namespaces.h"
1414 #include "comm.h"
15
+#include "map.h"
16
+#include "symbol.h"
1517 #include "unwind.h"
18
+#include "callchain.h"
1619
1720 #include <api/fs/fs.h>
1821
19
-int thread__init_map_groups(struct thread *thread, struct machine *machine)
22
+int thread__init_maps(struct thread *thread, struct machine *machine)
2023 {
2124 pid_t pid = thread->pid_;
2225
2326 if (pid == thread->tid || pid == -1) {
24
- thread->mg = map_groups__new(machine);
27
+ thread->maps = maps__new(machine);
2528 } else {
2629 struct thread *leader = __machine__findnew_thread(machine, pid, pid);
2730 if (leader) {
28
- thread->mg = map_groups__get(leader->mg);
31
+ thread->maps = maps__get(leader->maps);
2932 thread__put(leader);
3033 }
3134 }
3235
33
- return thread->mg ? 0 : -1;
36
+ return thread->maps ? 0 : -1;
3437 }
3538
3639 struct thread *thread__new(pid_t pid, pid_t tid)
....@@ -44,6 +47,7 @@
4447 thread->tid = tid;
4548 thread->ppid = -1;
4649 thread->cpu = -1;
50
+ thread->lbr_stitch_enable = false;
4751 INIT_LIST_HEAD(&thread->namespaces_list);
4852 INIT_LIST_HEAD(&thread->comm_list);
4953 init_rwsem(&thread->namespaces_lock);
....@@ -64,6 +68,7 @@
6468 RB_CLEAR_NODE(&thread->rb_node);
6569 /* Thread holds first ref to nsdata. */
6670 thread->nsinfo = nsinfo__new(pid);
71
+ srccode_state_init(&thread->srccode_state);
6772 }
6873
6974 return thread;
....@@ -82,30 +87,31 @@
8287
8388 thread_stack__free(thread);
8489
85
- if (thread->mg) {
86
- map_groups__put(thread->mg);
87
- thread->mg = NULL;
90
+ if (thread->maps) {
91
+ maps__put(thread->maps);
92
+ thread->maps = NULL;
8893 }
8994 down_write(&thread->namespaces_lock);
9095 list_for_each_entry_safe(namespaces, tmp_namespaces,
9196 &thread->namespaces_list, list) {
92
- list_del(&namespaces->list);
97
+ list_del_init(&namespaces->list);
9398 namespaces__free(namespaces);
9499 }
95100 up_write(&thread->namespaces_lock);
96101
97102 down_write(&thread->comm_lock);
98103 list_for_each_entry_safe(comm, tmp_comm, &thread->comm_list, list) {
99
- list_del(&comm->list);
104
+ list_del_init(&comm->list);
100105 comm__free(comm);
101106 }
102107 up_write(&thread->comm_lock);
103108
104
- unwind__finish_access(thread);
105109 nsinfo__zput(thread->nsinfo);
110
+ srccode_state_free(&thread->srccode_state);
106111
107112 exit_rwsem(&thread->namespaces_lock);
108113 exit_rwsem(&thread->comm_lock);
114
+ thread__free_stitch_list(thread);
109115 free(thread);
110116 }
111117
....@@ -120,10 +126,27 @@
120126 {
121127 if (thread && refcount_dec_and_test(&thread->refcnt)) {
122128 /*
123
- * Remove it from the dead_threads list, as last reference
124
- * is gone.
129
+ * Remove it from the dead threads list, as last reference is
130
+ * gone, if it is in a dead threads list.
131
+ *
132
+ * We may not be there anymore if say, the machine where it was
133
+ * stored was already deleted, so we already removed it from
134
+ * the dead threads and some other piece of code still keeps a
135
+ * reference.
136
+ *
137
+ * This is what 'perf sched' does and finally drops it in
138
+ * perf_sched__lat(), where it calls perf_sched__read_events(),
139
+ * that processes the events by creating a session and deleting
140
+ * it, which ends up destroying the list heads for the dead
141
+ * threads, but before it does that it removes all threads from
142
+ * it using list_del_init().
143
+ *
144
+ * So we need to check here if it is in a dead threads list and
145
+ * if so, remove it before finally deleting the thread, to avoid
146
+ * an use after free situation.
125147 */
126
- list_del_init(&thread->node);
148
+ if (!list_empty(&thread->node))
149
+ list_del_init(&thread->node);
127150 thread__delete(thread);
128151 }
129152 }
....@@ -136,19 +159,19 @@
136159 return list_first_entry(&thread->namespaces_list, struct namespaces, list);
137160 }
138161
139
-struct namespaces *thread__namespaces(const struct thread *thread)
162
+struct namespaces *thread__namespaces(struct thread *thread)
140163 {
141164 struct namespaces *ns;
142165
143
- down_read((struct rw_semaphore *)&thread->namespaces_lock);
166
+ down_read(&thread->namespaces_lock);
144167 ns = __thread__namespaces(thread);
145
- up_read((struct rw_semaphore *)&thread->namespaces_lock);
168
+ up_read(&thread->namespaces_lock);
146169
147170 return ns;
148171 }
149172
150173 static int __thread__set_namespaces(struct thread *thread, u64 timestamp,
151
- struct namespaces_event *event)
174
+ struct perf_record_namespaces *event)
152175 {
153176 struct namespaces *new, *curr = __thread__namespaces(thread);
154177
....@@ -172,7 +195,7 @@
172195 }
173196
174197 int thread__set_namespaces(struct thread *thread, u64 timestamp,
175
- struct namespaces_event *event)
198
+ struct perf_record_namespaces *event)
176199 {
177200 int ret;
178201
....@@ -230,7 +253,7 @@
230253 list_add(&new->list, &thread->comm_list);
231254
232255 if (exec)
233
- unwind__flush_access(thread);
256
+ unwind__flush_access(thread->maps);
234257 }
235258
236259 thread->comm_set = true;
....@@ -276,13 +299,13 @@
276299 return comm__str(comm);
277300 }
278301
279
-const char *thread__comm_str(const struct thread *thread)
302
+const char *thread__comm_str(struct thread *thread)
280303 {
281304 const char *str;
282305
283
- down_read((struct rw_semaphore *)&thread->comm_lock);
306
+ down_read(&thread->comm_lock);
284307 str = __thread__comm_str(thread);
285
- up_read((struct rw_semaphore *)&thread->comm_lock);
308
+ up_read(&thread->comm_lock);
286309
287310 return str;
288311 }
....@@ -303,19 +326,19 @@
303326 size_t thread__fprintf(struct thread *thread, FILE *fp)
304327 {
305328 return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) +
306
- map_groups__fprintf(thread->mg, fp);
329
+ maps__fprintf(thread->maps, fp);
307330 }
308331
309332 int thread__insert_map(struct thread *thread, struct map *map)
310333 {
311334 int ret;
312335
313
- ret = unwind__prepare_access(thread, map, NULL);
336
+ ret = unwind__prepare_access(thread->maps, map, NULL);
314337 if (ret)
315338 return ret;
316339
317
- map_groups__fixup_overlappings(thread->mg, map, stderr);
318
- map_groups__insert(thread->mg, map);
340
+ maps__fixup_overlappings(thread->maps, map, stderr);
341
+ maps__insert(thread->maps, map);
319342
320343 return 0;
321344 }
....@@ -324,13 +347,13 @@
324347 {
325348 bool initialized = false;
326349 int err = 0;
327
- struct maps *maps = &thread->mg->maps;
350
+ struct maps *maps = thread->maps;
328351 struct map *map;
329352
330353 down_read(&maps->lock);
331354
332
- for (map = maps__first(maps); map; map = map__next(map)) {
333
- err = unwind__prepare_access(thread, map, &initialized);
355
+ maps__for_each_entry(maps, map) {
356
+ err = unwind__prepare_access(thread->maps, map, &initialized);
334357 if (err || initialized)
335358 break;
336359 }
....@@ -344,33 +367,28 @@
344367 {
345368 int err = 0;
346369
347
- if (symbol_conf.use_callchain)
370
+ if (dwarf_callchain_users)
348371 err = __thread__prepare_access(thread);
349372
350373 return err;
351374 }
352375
353
-static int thread__clone_map_groups(struct thread *thread,
354
- struct thread *parent)
376
+static int thread__clone_maps(struct thread *thread, struct thread *parent, bool do_maps_clone)
355377 {
356378 /* This is new thread, we share map groups for process. */
357379 if (thread->pid_ == parent->pid_)
358380 return thread__prepare_access(thread);
359381
360
- if (thread->mg == parent->mg) {
382
+ if (thread->maps == parent->maps) {
361383 pr_debug("broken map groups on thread %d/%d parent %d/%d\n",
362384 thread->pid_, thread->tid, parent->pid_, parent->tid);
363385 return 0;
364386 }
365
-
366387 /* But this one is new process, copy maps. */
367
- if (map_groups__clone(thread, parent->mg) < 0)
368
- return -ENOMEM;
369
-
370
- return 0;
388
+ return do_maps_clone ? maps__clone(thread, parent->maps) : 0;
371389 }
372390
373
-int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
391
+int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone)
374392 {
375393 if (parent->comm_set) {
376394 const char *comm = thread__comm_str(parent);
....@@ -383,7 +401,7 @@
383401 }
384402
385403 thread->ppid = parent->tid;
386
- return thread__clone_map_groups(thread, parent);
404
+ return thread__clone_maps(thread, parent, do_maps_clone);
387405 }
388406
389407 void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
....@@ -414,3 +432,47 @@
414432
415433 return machine__find_thread(machine, thread->pid_, thread->pid_);
416434 }
435
+
436
+int thread__memcpy(struct thread *thread, struct machine *machine,
437
+ void *buf, u64 ip, int len, bool *is64bit)
438
+{
439
+ u8 cpumode = PERF_RECORD_MISC_USER;
440
+ struct addr_location al;
441
+ long offset;
442
+
443
+ if (machine__kernel_ip(machine, ip))
444
+ cpumode = PERF_RECORD_MISC_KERNEL;
445
+
446
+ if (!thread__find_map(thread, cpumode, ip, &al) || !al.map->dso ||
447
+ al.map->dso->data.status == DSO_DATA_STATUS_ERROR ||
448
+ map__load(al.map) < 0)
449
+ return -1;
450
+
451
+ offset = al.map->map_ip(al.map, ip);
452
+ if (is64bit)
453
+ *is64bit = al.map->dso->is_64_bit;
454
+
455
+ return dso__data_read_offset(al.map->dso, machine, offset, buf, len);
456
+}
457
+
458
+void thread__free_stitch_list(struct thread *thread)
459
+{
460
+ struct lbr_stitch *lbr_stitch = thread->lbr_stitch;
461
+ struct stitch_list *pos, *tmp;
462
+
463
+ if (!lbr_stitch)
464
+ return;
465
+
466
+ list_for_each_entry_safe(pos, tmp, &lbr_stitch->lists, node) {
467
+ list_del_init(&pos->node);
468
+ free(pos);
469
+ }
470
+
471
+ list_for_each_entry_safe(pos, tmp, &lbr_stitch->free_lists, node) {
472
+ list_del_init(&pos->node);
473
+ free(pos);
474
+ }
475
+
476
+ zfree(&lbr_stitch->prev_lbr_cursor);
477
+ zfree(&thread->lbr_stitch);
478
+}