hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/tools/perf/util/dso.c
....@@ -1,6 +1,8 @@
11 // SPDX-License-Identifier: GPL-2.0
22 #include <asm/bug.h>
33 #include <linux/kernel.h>
4
+#include <linux/string.h>
5
+#include <linux/zalloc.h>
46 #include <sys/time.h>
57 #include <sys/resource.h>
68 #include <sys/types.h>
....@@ -8,14 +10,21 @@
810 #include <unistd.h>
911 #include <errno.h>
1012 #include <fcntl.h>
13
+#include <stdlib.h>
14
+#include <bpf/libbpf.h>
15
+#include "bpf-event.h"
1116 #include "compress.h"
17
+#include "env.h"
18
+#include "namespaces.h"
1219 #include "path.h"
20
+#include "map.h"
1321 #include "symbol.h"
1422 #include "srcline.h"
1523 #include "dso.h"
24
+#include "dsos.h"
1625 #include "machine.h"
1726 #include "auxtrace.h"
18
-#include "util.h"
27
+#include "util.h" /* O_CLOEXEC for older systems */
1928 #include "debug.h"
2029 #include "string2.h"
2130 #include "vdso.h"
....@@ -163,9 +172,7 @@
163172 break;
164173 }
165174
166
- build_id__sprintf(dso->build_id,
167
- sizeof(dso->build_id),
168
- build_id_hex);
175
+ build_id__sprintf(&dso->bid, build_id_hex);
169176 len = __symbol__join_symfs(filename, size, "/usr/lib/debug/.build-id/");
170177 snprintf(filename + len, size - len, "%.2s/%s.debug",
171178 build_id_hex, build_id_hex + 2);
....@@ -197,6 +204,9 @@
197204 case DSO_BINARY_TYPE__KALLSYMS:
198205 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
199206 case DSO_BINARY_TYPE__JAVA_JIT:
207
+ case DSO_BINARY_TYPE__BPF_PROG_INFO:
208
+ case DSO_BINARY_TYPE__BPF_IMAGE:
209
+ case DSO_BINARY_TYPE__OOL:
200210 case DSO_BINARY_TYPE__NOT_FOUND:
201211 ret = -1;
202212 break;
....@@ -404,7 +414,7 @@
404414 return -ENOMEM;
405415 }
406416
407
- strxfrchar(m->name, '-', '_');
417
+ strreplace(m->name, '-', '_');
408418 }
409419
410420 return 0;
....@@ -442,7 +452,7 @@
442452
443453 static void dso__list_del(struct dso *dso)
444454 {
445
- list_del(&dso->data.open_entry);
455
+ list_del_init(&dso->data.open_entry);
446456 WARN_ONCE(dso__data_open_cnt <= 0,
447457 "DSO data fd counter out of bounds.");
448458 dso__data_open_cnt--;
....@@ -718,6 +728,44 @@
718728 return false;
719729 }
720730
731
+static ssize_t bpf_read(struct dso *dso, u64 offset, char *data)
732
+{
733
+ struct bpf_prog_info_node *node;
734
+ ssize_t size = DSO__DATA_CACHE_SIZE;
735
+ u64 len;
736
+ u8 *buf;
737
+
738
+ node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, dso->bpf_prog.id);
739
+ if (!node || !node->info_linear) {
740
+ dso->data.status = DSO_DATA_STATUS_ERROR;
741
+ return -1;
742
+ }
743
+
744
+ len = node->info_linear->info.jited_prog_len;
745
+ buf = (u8 *)(uintptr_t)node->info_linear->info.jited_prog_insns;
746
+
747
+ if (offset >= len)
748
+ return -1;
749
+
750
+ size = (ssize_t)min(len - offset, (u64)size);
751
+ memcpy(data, buf + offset, size);
752
+ return size;
753
+}
754
+
755
+static int bpf_size(struct dso *dso)
756
+{
757
+ struct bpf_prog_info_node *node;
758
+
759
+ node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, dso->bpf_prog.id);
760
+ if (!node || !node->info_linear) {
761
+ dso->data.status = DSO_DATA_STATUS_ERROR;
762
+ return -1;
763
+ }
764
+
765
+ dso->data.file_size = node->info_linear->info.jited_prog_len;
766
+ return 0;
767
+}
768
+
721769 static void
722770 dso_cache__free(struct dso *dso)
723771 {
....@@ -736,7 +784,7 @@
736784 pthread_mutex_unlock(&dso->lock);
737785 }
738786
739
-static struct dso_cache *dso_cache__find(struct dso *dso, u64 offset)
787
+static struct dso_cache *__dso_cache__find(struct dso *dso, u64 offset)
740788 {
741789 const struct rb_root *root = &dso->data.cache;
742790 struct rb_node * const *p = &root->rb_node;
....@@ -795,94 +843,113 @@
795843 return cache;
796844 }
797845
798
-static ssize_t
799
-dso_cache__memcpy(struct dso_cache *cache, u64 offset,
800
- u8 *data, u64 size)
846
+static ssize_t dso_cache__memcpy(struct dso_cache *cache, u64 offset, u8 *data,
847
+ u64 size, bool out)
801848 {
802849 u64 cache_offset = offset - cache->offset;
803850 u64 cache_size = min(cache->size - cache_offset, size);
804851
805
- memcpy(data, cache->data + cache_offset, cache_size);
852
+ if (out)
853
+ memcpy(data, cache->data + cache_offset, cache_size);
854
+ else
855
+ memcpy(cache->data + cache_offset, data, cache_size);
806856 return cache_size;
807857 }
808858
809
-static ssize_t
810
-dso_cache__read(struct dso *dso, struct machine *machine,
811
- u64 offset, u8 *data, ssize_t size)
859
+static ssize_t file_read(struct dso *dso, struct machine *machine,
860
+ u64 offset, char *data)
812861 {
813
- struct dso_cache *cache;
814
- struct dso_cache *old;
815862 ssize_t ret;
816863
817
- do {
818
- u64 cache_offset;
864
+ pthread_mutex_lock(&dso__data_open_lock);
819865
820
- cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
821
- if (!cache)
822
- return -ENOMEM;
866
+ /*
867
+ * dso->data.fd might be closed if other thread opened another
868
+ * file (dso) due to open file limit (RLIMIT_NOFILE).
869
+ */
870
+ try_to_open_dso(dso, machine);
823871
824
- pthread_mutex_lock(&dso__data_open_lock);
825
-
826
- /*
827
- * dso->data.fd might be closed if other thread opened another
828
- * file (dso) due to open file limit (RLIMIT_NOFILE).
829
- */
830
- try_to_open_dso(dso, machine);
831
-
832
- if (dso->data.fd < 0) {
833
- ret = -errno;
834
- dso->data.status = DSO_DATA_STATUS_ERROR;
835
- break;
836
- }
837
-
838
- cache_offset = offset & DSO__DATA_CACHE_MASK;
839
-
840
- ret = pread(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE, cache_offset);
841
- if (ret <= 0)
842
- break;
843
-
844
- cache->offset = cache_offset;
845
- cache->size = ret;
846
- } while (0);
847
-
848
- pthread_mutex_unlock(&dso__data_open_lock);
849
-
850
- if (ret > 0) {
851
- old = dso_cache__insert(dso, cache);
852
- if (old) {
853
- /* we lose the race */
854
- free(cache);
855
- cache = old;
856
- }
857
-
858
- ret = dso_cache__memcpy(cache, offset, data, size);
872
+ if (dso->data.fd < 0) {
873
+ dso->data.status = DSO_DATA_STATUS_ERROR;
874
+ ret = -errno;
875
+ goto out;
859876 }
860877
861
- if (ret <= 0)
862
- free(cache);
863
-
878
+ ret = pread(dso->data.fd, data, DSO__DATA_CACHE_SIZE, offset);
879
+out:
880
+ pthread_mutex_unlock(&dso__data_open_lock);
864881 return ret;
865882 }
866883
867
-static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
868
- u64 offset, u8 *data, ssize_t size)
884
+static struct dso_cache *dso_cache__populate(struct dso *dso,
885
+ struct machine *machine,
886
+ u64 offset, ssize_t *ret)
887
+{
888
+ u64 cache_offset = offset & DSO__DATA_CACHE_MASK;
889
+ struct dso_cache *cache;
890
+ struct dso_cache *old;
891
+
892
+ cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
893
+ if (!cache) {
894
+ *ret = -ENOMEM;
895
+ return NULL;
896
+ }
897
+
898
+ if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
899
+ *ret = bpf_read(dso, cache_offset, cache->data);
900
+ else if (dso->binary_type == DSO_BINARY_TYPE__OOL)
901
+ *ret = DSO__DATA_CACHE_SIZE;
902
+ else
903
+ *ret = file_read(dso, machine, cache_offset, cache->data);
904
+
905
+ if (*ret <= 0) {
906
+ free(cache);
907
+ return NULL;
908
+ }
909
+
910
+ cache->offset = cache_offset;
911
+ cache->size = *ret;
912
+
913
+ old = dso_cache__insert(dso, cache);
914
+ if (old) {
915
+ /* we lose the race */
916
+ free(cache);
917
+ cache = old;
918
+ }
919
+
920
+ return cache;
921
+}
922
+
923
+static struct dso_cache *dso_cache__find(struct dso *dso,
924
+ struct machine *machine,
925
+ u64 offset,
926
+ ssize_t *ret)
927
+{
928
+ struct dso_cache *cache = __dso_cache__find(dso, offset);
929
+
930
+ return cache ? cache : dso_cache__populate(dso, machine, offset, ret);
931
+}
932
+
933
+static ssize_t dso_cache_io(struct dso *dso, struct machine *machine,
934
+ u64 offset, u8 *data, ssize_t size, bool out)
869935 {
870936 struct dso_cache *cache;
937
+ ssize_t ret = 0;
871938
872
- cache = dso_cache__find(dso, offset);
873
- if (cache)
874
- return dso_cache__memcpy(cache, offset, data, size);
875
- else
876
- return dso_cache__read(dso, machine, offset, data, size);
939
+ cache = dso_cache__find(dso, machine, offset, &ret);
940
+ if (!cache)
941
+ return ret;
942
+
943
+ return dso_cache__memcpy(cache, offset, data, size, out);
877944 }
878945
879946 /*
880947 * Reads and caches dso data DSO__DATA_CACHE_SIZE size chunks
881948 * in the rb_tree. Any read to already cached data is served
882
- * by cached data.
949
+ * by cached data. Writes update the cache only, not the backing file.
883950 */
884
-static ssize_t cached_read(struct dso *dso, struct machine *machine,
885
- u64 offset, u8 *data, ssize_t size)
951
+static ssize_t cached_io(struct dso *dso, struct machine *machine,
952
+ u64 offset, u8 *data, ssize_t size, bool out)
886953 {
887954 ssize_t r = 0;
888955 u8 *p = data;
....@@ -890,7 +957,7 @@
890957 do {
891958 ssize_t ret;
892959
893
- ret = dso_cache_read(dso, machine, offset, p, size);
960
+ ret = dso_cache_io(dso, machine, offset, p, size, out);
894961 if (ret < 0)
895962 return ret;
896963
....@@ -910,17 +977,11 @@
910977 return r;
911978 }
912979
913
-static int data_file_size(struct dso *dso, struct machine *machine)
980
+static int file_size(struct dso *dso, struct machine *machine)
914981 {
915982 int ret = 0;
916983 struct stat st;
917984 char sbuf[STRERR_BUFSIZE];
918
-
919
- if (dso->data.file_size)
920
- return 0;
921
-
922
- if (dso->data.status == DSO_DATA_STATUS_ERROR)
923
- return -1;
924985
925986 pthread_mutex_lock(&dso__data_open_lock);
926987
....@@ -950,6 +1011,20 @@
9501011 return ret;
9511012 }
9521013
1014
+int dso__data_file_size(struct dso *dso, struct machine *machine)
1015
+{
1016
+ if (dso->data.file_size)
1017
+ return 0;
1018
+
1019
+ if (dso->data.status == DSO_DATA_STATUS_ERROR)
1020
+ return -1;
1021
+
1022
+ if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
1023
+ return bpf_size(dso);
1024
+
1025
+ return file_size(dso, machine);
1026
+}
1027
+
9531028 /**
9541029 * dso__data_size - Return dso data size
9551030 * @dso: dso object
....@@ -959,17 +1034,18 @@
9591034 */
9601035 off_t dso__data_size(struct dso *dso, struct machine *machine)
9611036 {
962
- if (data_file_size(dso, machine))
1037
+ if (dso__data_file_size(dso, machine))
9631038 return -1;
9641039
9651040 /* For now just estimate dso data size is close to file size */
9661041 return dso->data.file_size;
9671042 }
9681043
969
-static ssize_t data_read_offset(struct dso *dso, struct machine *machine,
970
- u64 offset, u8 *data, ssize_t size)
1044
+static ssize_t data_read_write_offset(struct dso *dso, struct machine *machine,
1045
+ u64 offset, u8 *data, ssize_t size,
1046
+ bool out)
9711047 {
972
- if (data_file_size(dso, machine))
1048
+ if (dso__data_file_size(dso, machine))
9731049 return -1;
9741050
9751051 /* Check the offset sanity. */
....@@ -979,7 +1055,7 @@
9791055 if (offset + size < offset)
9801056 return -1;
9811057
982
- return cached_read(dso, machine, offset, data, size);
1058
+ return cached_io(dso, machine, offset, data, size, out);
9831059 }
9841060
9851061 /**
....@@ -999,7 +1075,7 @@
9991075 if (dso->data.status == DSO_DATA_STATUS_ERROR)
10001076 return -1;
10011077
1002
- return data_read_offset(dso, machine, offset, data, size);
1078
+ return data_read_write_offset(dso, machine, offset, data, size, true);
10031079 }
10041080
10051081 /**
....@@ -1018,6 +1094,46 @@
10181094 {
10191095 u64 offset = map->map_ip(map, addr);
10201096 return dso__data_read_offset(dso, machine, offset, data, size);
1097
+}
1098
+
1099
+/**
1100
+ * dso__data_write_cache_offs - Write data to dso data cache at file offset
1101
+ * @dso: dso object
1102
+ * @machine: machine object
1103
+ * @offset: file offset
1104
+ * @data: buffer to write
1105
+ * @size: size of the @data buffer
1106
+ *
1107
+ * Write into the dso file data cache, but do not change the file itself.
1108
+ */
1109
+ssize_t dso__data_write_cache_offs(struct dso *dso, struct machine *machine,
1110
+ u64 offset, const u8 *data_in, ssize_t size)
1111
+{
1112
+ u8 *data = (u8 *)data_in; /* cast away const to use same fns for r/w */
1113
+
1114
+ if (dso->data.status == DSO_DATA_STATUS_ERROR)
1115
+ return -1;
1116
+
1117
+ return data_read_write_offset(dso, machine, offset, data, size, false);
1118
+}
1119
+
1120
+/**
1121
+ * dso__data_write_cache_addr - Write data to dso data cache at dso address
1122
+ * @dso: dso object
1123
+ * @machine: machine object
1124
+ * @add: virtual memory address
1125
+ * @data: buffer to write
1126
+ * @size: size of the @data buffer
1127
+ *
1128
+ * External interface to write into the dso file data cache, but do not change
1129
+ * the file itself.
1130
+ */
1131
+ssize_t dso__data_write_cache_addr(struct dso *dso, struct map *map,
1132
+ struct machine *machine, u64 addr,
1133
+ const u8 *data, ssize_t size)
1134
+{
1135
+ u64 offset = map->map_ip(map, addr);
1136
+ return dso__data_write_cache_offs(dso, machine, offset, data, size);
10211137 }
10221138
10231139 struct map *dso__new_map(const char *name)
....@@ -1053,67 +1169,7 @@
10531169 return dso;
10541170 }
10551171
1056
-/*
1057
- * Find a matching entry and/or link current entry to RB tree.
1058
- * Either one of the dso or name parameter must be non-NULL or the
1059
- * function will not work.
1060
- */
1061
-static struct dso *__dso__findlink_by_longname(struct rb_root *root,
1062
- struct dso *dso, const char *name)
1063
-{
1064
- struct rb_node **p = &root->rb_node;
1065
- struct rb_node *parent = NULL;
1066
-
1067
- if (!name)
1068
- name = dso->long_name;
1069
- /*
1070
- * Find node with the matching name
1071
- */
1072
- while (*p) {
1073
- struct dso *this = rb_entry(*p, struct dso, rb_node);
1074
- int rc = strcmp(name, this->long_name);
1075
-
1076
- parent = *p;
1077
- if (rc == 0) {
1078
- /*
1079
- * In case the new DSO is a duplicate of an existing
1080
- * one, print a one-time warning & put the new entry
1081
- * at the end of the list of duplicates.
1082
- */
1083
- if (!dso || (dso == this))
1084
- return this; /* Find matching dso */
1085
- /*
1086
- * The core kernel DSOs may have duplicated long name.
1087
- * In this case, the short name should be different.
1088
- * Comparing the short names to differentiate the DSOs.
1089
- */
1090
- rc = strcmp(dso->short_name, this->short_name);
1091
- if (rc == 0) {
1092
- pr_err("Duplicated dso name: %s\n", name);
1093
- return NULL;
1094
- }
1095
- }
1096
- if (rc < 0)
1097
- p = &parent->rb_left;
1098
- else
1099
- p = &parent->rb_right;
1100
- }
1101
- if (dso) {
1102
- /* Add new node and rebalance tree */
1103
- rb_link_node(&dso->rb_node, parent, p);
1104
- rb_insert_color(&dso->rb_node, root);
1105
- dso->root = root;
1106
- }
1107
- return NULL;
1108
-}
1109
-
1110
-static inline struct dso *__dso__find_by_longname(struct rb_root *root,
1111
- const char *name)
1112
-{
1113
- return __dso__findlink_by_longname(root, NULL, name);
1114
-}
1115
-
1116
-void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
1172
+static void dso__set_long_name_id(struct dso *dso, const char *name, struct dso_id *id, bool name_allocated)
11171173 {
11181174 struct rb_root *root = dso->root;
11191175
....@@ -1126,8 +1182,8 @@
11261182 if (root) {
11271183 rb_erase(&dso->rb_node, root);
11281184 /*
1129
- * __dso__findlink_by_longname() isn't guaranteed to add it
1130
- * back, so a clean removal is required here.
1185
+ * __dsos__findnew_link_by_longname_id() isn't guaranteed to
1186
+ * add it back, so a clean removal is required here.
11311187 */
11321188 RB_CLEAR_NODE(&dso->rb_node);
11331189 dso->root = NULL;
....@@ -1138,7 +1194,12 @@
11381194 dso->long_name_allocated = name_allocated;
11391195
11401196 if (root)
1141
- __dso__findlink_by_longname(root, dso, NULL);
1197
+ __dsos__findnew_link_by_longname_id(root, dso, NULL, id);
1198
+}
1199
+
1200
+void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
1201
+{
1202
+ dso__set_long_name_id(dso, name, NULL, name_allocated);
11421203 }
11431204
11441205 void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
....@@ -1152,32 +1213,6 @@
11521213 dso->short_name = name;
11531214 dso->short_name_len = strlen(name);
11541215 dso->short_name_allocated = name_allocated;
1155
-}
1156
-
1157
-static void dso__set_basename(struct dso *dso)
1158
-{
1159
- /*
1160
- * basename() may modify path buffer, so we must pass
1161
- * a copy.
1162
- */
1163
- char *base, *lname = strdup(dso->long_name);
1164
-
1165
- if (!lname)
1166
- return;
1167
-
1168
- /*
1169
- * basename() may return a pointer to internal
1170
- * storage which is reused in subsequent calls
1171
- * so copy the result.
1172
- */
1173
- base = strdup(basename(lname));
1174
-
1175
- free(lname);
1176
-
1177
- if (!base)
1178
- return;
1179
-
1180
- dso__set_short_name(dso, base, true);
11811216 }
11821217
11831218 int dso__name_len(const struct dso *dso)
....@@ -1205,18 +1240,20 @@
12051240 dso->sorted_by_name = true;
12061241 }
12071242
1208
-struct dso *dso__new(const char *name)
1243
+struct dso *dso__new_id(const char *name, struct dso_id *id)
12091244 {
12101245 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
12111246
12121247 if (dso != NULL) {
12131248 strcpy(dso->name, name);
1214
- dso__set_long_name(dso, dso->name, false);
1249
+ if (id)
1250
+ dso->id = *id;
1251
+ dso__set_long_name_id(dso, dso->name, id, false);
12151252 dso__set_short_name(dso, dso->name, false);
1216
- dso->symbols = dso->symbol_names = RB_ROOT;
1253
+ dso->symbols = dso->symbol_names = RB_ROOT_CACHED;
12171254 dso->data.cache = RB_ROOT;
1218
- dso->inlined_nodes = RB_ROOT;
1219
- dso->srclines = RB_ROOT;
1255
+ dso->inlined_nodes = RB_ROOT_CACHED;
1256
+ dso->srclines = RB_ROOT_CACHED;
12201257 dso->data.fd = -1;
12211258 dso->data.status = DSO_DATA_STATUS_UNKNOWN;
12221259 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
....@@ -1228,7 +1265,7 @@
12281265 dso->has_build_id = 0;
12291266 dso->has_srcline = 1;
12301267 dso->a2l_fails = 1;
1231
- dso->kernel = DSO_TYPE_USER;
1268
+ dso->kernel = DSO_SPACE__USER;
12321269 dso->needs_swap = DSO_SWAP__UNSET;
12331270 dso->comp = COMP_ID__NONE;
12341271 RB_CLEAR_NODE(&dso->rb_node);
....@@ -1240,6 +1277,11 @@
12401277 }
12411278
12421279 return dso;
1280
+}
1281
+
1282
+struct dso *dso__new(const char *name)
1283
+{
1284
+ return dso__new_id(name, NULL);
12431285 }
12441286
12451287 void dso__delete(struct dso *dso)
....@@ -1286,15 +1328,26 @@
12861328 dso__delete(dso);
12871329 }
12881330
1289
-void dso__set_build_id(struct dso *dso, void *build_id)
1331
+void dso__set_build_id(struct dso *dso, struct build_id *bid)
12901332 {
1291
- memcpy(dso->build_id, build_id, sizeof(dso->build_id));
1333
+ dso->bid = *bid;
12921334 dso->has_build_id = 1;
12931335 }
12941336
1295
-bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
1337
+bool dso__build_id_equal(const struct dso *dso, struct build_id *bid)
12961338 {
1297
- return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
1339
+ if (dso->bid.size > bid->size && dso->bid.size == BUILD_ID_SIZE) {
1340
+ /*
1341
+ * For the backward compatibility, it allows a build-id has
1342
+ * trailing zeros.
1343
+ */
1344
+ return !memcmp(dso->bid.data, bid->data, bid->size) &&
1345
+ !memchr_inv(&dso->bid.data[bid->size], 0,
1346
+ dso->bid.size - bid->size);
1347
+ }
1348
+
1349
+ return dso->bid.size == bid->size &&
1350
+ memcmp(dso->bid.data, bid->data, dso->bid.size) == 0;
12981351 }
12991352
13001353 void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
....@@ -1304,8 +1357,7 @@
13041357 if (machine__is_default_guest(machine))
13051358 return;
13061359 sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
1307
- if (sysfs__read_build_id(path, dso->build_id,
1308
- sizeof(dso->build_id)) == 0)
1360
+ if (sysfs__read_build_id(path, &dso->bid) == 0)
13091361 dso->has_build_id = true;
13101362 }
13111363
....@@ -1323,155 +1375,17 @@
13231375 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
13241376 root_dir, (int)strlen(name) - 1, name);
13251377
1326
- if (sysfs__read_build_id(filename, dso->build_id,
1327
- sizeof(dso->build_id)) == 0)
1378
+ if (sysfs__read_build_id(filename, &dso->bid) == 0)
13281379 dso->has_build_id = true;
13291380
13301381 return 0;
13311382 }
13321383
1333
-bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1334
-{
1335
- bool have_build_id = false;
1336
- struct dso *pos;
1337
- struct nscookie nsc;
1338
-
1339
- list_for_each_entry(pos, head, node) {
1340
- if (with_hits && !pos->hit && !dso__is_vdso(pos))
1341
- continue;
1342
- if (pos->has_build_id) {
1343
- have_build_id = true;
1344
- continue;
1345
- }
1346
- nsinfo__mountns_enter(pos->nsinfo, &nsc);
1347
- if (filename__read_build_id(pos->long_name, pos->build_id,
1348
- sizeof(pos->build_id)) > 0) {
1349
- have_build_id = true;
1350
- pos->has_build_id = true;
1351
- }
1352
- nsinfo__mountns_exit(&nsc);
1353
- }
1354
-
1355
- return have_build_id;
1356
-}
1357
-
1358
-void __dsos__add(struct dsos *dsos, struct dso *dso)
1359
-{
1360
- list_add_tail(&dso->node, &dsos->head);
1361
- __dso__findlink_by_longname(&dsos->root, dso, NULL);
1362
- /*
1363
- * It is now in the linked list, grab a reference, then garbage collect
1364
- * this when needing memory, by looking at LRU dso instances in the
1365
- * list with atomic_read(&dso->refcnt) == 1, i.e. no references
1366
- * anywhere besides the one for the list, do, under a lock for the
1367
- * list: remove it from the list, then a dso__put(), that probably will
1368
- * be the last and will then call dso__delete(), end of life.
1369
- *
1370
- * That, or at the end of the 'struct machine' lifetime, when all
1371
- * 'struct dso' instances will be removed from the list, in
1372
- * dsos__exit(), if they have no other reference from some other data
1373
- * structure.
1374
- *
1375
- * E.g.: after processing a 'perf.data' file and storing references
1376
- * to objects instantiated while processing events, we will have
1377
- * references to the 'thread', 'map', 'dso' structs all from 'struct
1378
- * hist_entry' instances, but we may not need anything not referenced,
1379
- * so we might as well call machines__exit()/machines__delete() and
1380
- * garbage collect it.
1381
- */
1382
- dso__get(dso);
1383
-}
1384
-
1385
-void dsos__add(struct dsos *dsos, struct dso *dso)
1386
-{
1387
- down_write(&dsos->lock);
1388
- __dsos__add(dsos, dso);
1389
- up_write(&dsos->lock);
1390
-}
1391
-
1392
-struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
1393
-{
1394
- struct dso *pos;
1395
-
1396
- if (cmp_short) {
1397
- list_for_each_entry(pos, &dsos->head, node)
1398
- if (strcmp(pos->short_name, name) == 0)
1399
- return pos;
1400
- return NULL;
1401
- }
1402
- return __dso__find_by_longname(&dsos->root, name);
1403
-}
1404
-
1405
-struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
1406
-{
1407
- struct dso *dso;
1408
- down_read(&dsos->lock);
1409
- dso = __dsos__find(dsos, name, cmp_short);
1410
- up_read(&dsos->lock);
1411
- return dso;
1412
-}
1413
-
1414
-struct dso *__dsos__addnew(struct dsos *dsos, const char *name)
1415
-{
1416
- struct dso *dso = dso__new(name);
1417
-
1418
- if (dso != NULL) {
1419
- __dsos__add(dsos, dso);
1420
- dso__set_basename(dso);
1421
- /* Put dso here because __dsos_add already got it */
1422
- dso__put(dso);
1423
- }
1424
- return dso;
1425
-}
1426
-
1427
-struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
1428
-{
1429
- struct dso *dso = __dsos__find(dsos, name, false);
1430
-
1431
- return dso ? dso : __dsos__addnew(dsos, name);
1432
-}
1433
-
1434
-struct dso *dsos__findnew(struct dsos *dsos, const char *name)
1435
-{
1436
- struct dso *dso;
1437
- down_write(&dsos->lock);
1438
- dso = dso__get(__dsos__findnew(dsos, name));
1439
- up_write(&dsos->lock);
1440
- return dso;
1441
-}
1442
-
1443
-size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
1444
- bool (skip)(struct dso *dso, int parm), int parm)
1445
-{
1446
- struct dso *pos;
1447
- size_t ret = 0;
1448
-
1449
- list_for_each_entry(pos, head, node) {
1450
- if (skip && skip(pos, parm))
1451
- continue;
1452
- ret += dso__fprintf_buildid(pos, fp);
1453
- ret += fprintf(fp, " %s\n", pos->long_name);
1454
- }
1455
- return ret;
1456
-}
1457
-
1458
-size_t __dsos__fprintf(struct list_head *head, FILE *fp)
1459
-{
1460
- struct dso *pos;
1461
- size_t ret = 0;
1462
-
1463
- list_for_each_entry(pos, head, node) {
1464
- ret += dso__fprintf(pos, fp);
1465
- }
1466
-
1467
- return ret;
1468
-}
1469
-
1470
-size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
1384
+static size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
14711385 {
14721386 char sbuild_id[SBUILD_ID_SIZE];
14731387
1474
- build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1388
+ build_id__sprintf(&dso->bid, sbuild_id);
14751389 return fprintf(fp, "%s", sbuild_id);
14761390 }
14771391
....@@ -1485,7 +1399,7 @@
14851399 ret += fprintf(fp, "%sloaded, ", dso__loaded(dso) ? "" : "NOT ");
14861400 ret += dso__fprintf_buildid(dso, fp);
14871401 ret += fprintf(fp, ")\n");
1488
- for (nd = rb_first(&dso->symbols); nd; nd = rb_next(nd)) {
1402
+ for (nd = rb_first_cached(&dso->symbols); nd; nd = rb_next(nd)) {
14891403 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
14901404 ret += symbol__fprintf(pos, fp);
14911405 }