~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/dso.c

Version: ~ [ linux-5.3 ] ~ [ linux-5.2.14 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.72 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.143 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.192 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.192 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.73 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #include "symbol.h"
  2 #include "dso.h"
  3 #include "machine.h"
  4 #include "util.h"
  5 #include "debug.h"
  6 
  7 char dso__symtab_origin(const struct dso *dso)
  8 {
  9         static const char origin[] = {
 10                 [DSO_BINARY_TYPE__KALLSYMS]             = 'k',
 11                 [DSO_BINARY_TYPE__VMLINUX]              = 'v',
 12                 [DSO_BINARY_TYPE__JAVA_JIT]             = 'j',
 13                 [DSO_BINARY_TYPE__DEBUGLINK]            = 'l',
 14                 [DSO_BINARY_TYPE__BUILD_ID_CACHE]       = 'B',
 15                 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO]     = 'f',
 16                 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO]     = 'u',
 17                 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO]    = 'b',
 18                 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO]      = 'd',
 19                 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE]  = 'K',
 20                 [DSO_BINARY_TYPE__GUEST_KALLSYMS]       = 'g',
 21                 [DSO_BINARY_TYPE__GUEST_KMODULE]        = 'G',
 22                 [DSO_BINARY_TYPE__GUEST_VMLINUX]        = 'V',
 23         };
 24 
 25         if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
 26                 return '!';
 27         return origin[dso->symtab_type];
 28 }
 29 
 30 int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
 31                           char *root_dir, char *file, size_t size)
 32 {
 33         char build_id_hex[BUILD_ID_SIZE * 2 + 1];
 34         int ret = 0;
 35 
 36         switch (type) {
 37         case DSO_BINARY_TYPE__DEBUGLINK: {
 38                 char *debuglink;
 39 
 40                 strncpy(file, dso->long_name, size);
 41                 debuglink = file + dso->long_name_len;
 42                 while (debuglink != file && *debuglink != '/')
 43                         debuglink--;
 44                 if (*debuglink == '/')
 45                         debuglink++;
 46                 filename__read_debuglink(dso->long_name, debuglink,
 47                                          size - (debuglink - file));
 48                 }
 49                 break;
 50         case DSO_BINARY_TYPE__BUILD_ID_CACHE:
 51                 /* skip the locally configured cache if a symfs is given */
 52                 if (symbol_conf.symfs[0] ||
 53                     (dso__build_id_filename(dso, file, size) == NULL))
 54                         ret = -1;
 55                 break;
 56 
 57         case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
 58                 snprintf(file, size, "%s/usr/lib/debug%s.debug",
 59                          symbol_conf.symfs, dso->long_name);
 60                 break;
 61 
 62         case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
 63                 snprintf(file, size, "%s/usr/lib/debug%s",
 64                          symbol_conf.symfs, dso->long_name);
 65                 break;
 66 
 67         case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
 68                 if (!dso->has_build_id) {
 69                         ret = -1;
 70                         break;
 71                 }
 72 
 73                 build_id__sprintf(dso->build_id,
 74                                   sizeof(dso->build_id),
 75                                   build_id_hex);
 76                 snprintf(file, size,
 77                          "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
 78                          symbol_conf.symfs, build_id_hex, build_id_hex + 2);
 79                 break;
 80 
 81         case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
 82                 snprintf(file, size, "%s%s",
 83                          symbol_conf.symfs, dso->long_name);
 84                 break;
 85 
 86         case DSO_BINARY_TYPE__GUEST_KMODULE:
 87                 snprintf(file, size, "%s%s%s", symbol_conf.symfs,
 88                          root_dir, dso->long_name);
 89                 break;
 90 
 91         case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
 92                 snprintf(file, size, "%s%s", symbol_conf.symfs,
 93                          dso->long_name);
 94                 break;
 95 
 96         default:
 97         case DSO_BINARY_TYPE__KALLSYMS:
 98         case DSO_BINARY_TYPE__VMLINUX:
 99         case DSO_BINARY_TYPE__GUEST_KALLSYMS:
100         case DSO_BINARY_TYPE__GUEST_VMLINUX:
101         case DSO_BINARY_TYPE__JAVA_JIT:
102         case DSO_BINARY_TYPE__NOT_FOUND:
103                 ret = -1;
104                 break;
105         }
106 
107         return ret;
108 }
109 
110 static int open_dso(struct dso *dso, struct machine *machine)
111 {
112         char *root_dir = (char *) "";
113         char *name;
114         int fd;
115 
116         name = malloc(PATH_MAX);
117         if (!name)
118                 return -ENOMEM;
119 
120         if (machine)
121                 root_dir = machine->root_dir;
122 
123         if (dso__binary_type_file(dso, dso->data_type,
124                                   root_dir, name, PATH_MAX)) {
125                 free(name);
126                 return -EINVAL;
127         }
128 
129         fd = open(name, O_RDONLY);
130         free(name);
131         return fd;
132 }
133 
134 int dso__data_fd(struct dso *dso, struct machine *machine)
135 {
136         static enum dso_binary_type binary_type_data[] = {
137                 DSO_BINARY_TYPE__BUILD_ID_CACHE,
138                 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
139                 DSO_BINARY_TYPE__NOT_FOUND,
140         };
141         int i = 0;
142 
143         if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
144                 return open_dso(dso, machine);
145 
146         do {
147                 int fd;
148 
149                 dso->data_type = binary_type_data[i++];
150 
151                 fd = open_dso(dso, machine);
152                 if (fd >= 0)
153                         return fd;
154 
155         } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
156 
157         return -EINVAL;
158 }
159 
160 static void
161 dso_cache__free(struct rb_root *root)
162 {
163         struct rb_node *next = rb_first(root);
164 
165         while (next) {
166                 struct dso_cache *cache;
167 
168                 cache = rb_entry(next, struct dso_cache, rb_node);
169                 next = rb_next(&cache->rb_node);
170                 rb_erase(&cache->rb_node, root);
171                 free(cache);
172         }
173 }
174 
175 static struct dso_cache*
176 dso_cache__find(struct rb_root *root, u64 offset)
177 {
178         struct rb_node **p = &root->rb_node;
179         struct rb_node *parent = NULL;
180         struct dso_cache *cache;
181 
182         while (*p != NULL) {
183                 u64 end;
184 
185                 parent = *p;
186                 cache = rb_entry(parent, struct dso_cache, rb_node);
187                 end = cache->offset + DSO__DATA_CACHE_SIZE;
188 
189                 if (offset < cache->offset)
190                         p = &(*p)->rb_left;
191                 else if (offset >= end)
192                         p = &(*p)->rb_right;
193                 else
194                         return cache;
195         }
196         return NULL;
197 }
198 
199 static void
200 dso_cache__insert(struct rb_root *root, struct dso_cache *new)
201 {
202         struct rb_node **p = &root->rb_node;
203         struct rb_node *parent = NULL;
204         struct dso_cache *cache;
205         u64 offset = new->offset;
206 
207         while (*p != NULL) {
208                 u64 end;
209 
210                 parent = *p;
211                 cache = rb_entry(parent, struct dso_cache, rb_node);
212                 end = cache->offset + DSO__DATA_CACHE_SIZE;
213 
214                 if (offset < cache->offset)
215                         p = &(*p)->rb_left;
216                 else if (offset >= end)
217                         p = &(*p)->rb_right;
218         }
219 
220         rb_link_node(&new->rb_node, parent, p);
221         rb_insert_color(&new->rb_node, root);
222 }
223 
224 static ssize_t
225 dso_cache__memcpy(struct dso_cache *cache, u64 offset,
226                   u8 *data, u64 size)
227 {
228         u64 cache_offset = offset - cache->offset;
229         u64 cache_size   = min(cache->size - cache_offset, size);
230 
231         memcpy(data, cache->data + cache_offset, cache_size);
232         return cache_size;
233 }
234 
235 static ssize_t
236 dso_cache__read(struct dso *dso, struct machine *machine,
237                  u64 offset, u8 *data, ssize_t size)
238 {
239         struct dso_cache *cache;
240         ssize_t ret;
241         int fd;
242 
243         fd = dso__data_fd(dso, machine);
244         if (fd < 0)
245                 return -1;
246 
247         do {
248                 u64 cache_offset;
249 
250                 ret = -ENOMEM;
251 
252                 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
253                 if (!cache)
254                         break;
255 
256                 cache_offset = offset & DSO__DATA_CACHE_MASK;
257                 ret = -EINVAL;
258 
259                 if (-1 == lseek(fd, cache_offset, SEEK_SET))
260                         break;
261 
262                 ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
263                 if (ret <= 0)
264                         break;
265 
266                 cache->offset = cache_offset;
267                 cache->size   = ret;
268                 dso_cache__insert(&dso->cache, cache);
269 
270                 ret = dso_cache__memcpy(cache, offset, data, size);
271 
272         } while (0);
273 
274         if (ret <= 0)
275                 free(cache);
276 
277         close(fd);
278         return ret;
279 }
280 
281 static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
282                               u64 offset, u8 *data, ssize_t size)
283 {
284         struct dso_cache *cache;
285 
286         cache = dso_cache__find(&dso->cache, offset);
287         if (cache)
288                 return dso_cache__memcpy(cache, offset, data, size);
289         else
290                 return dso_cache__read(dso, machine, offset, data, size);
291 }
292 
293 ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
294                               u64 offset, u8 *data, ssize_t size)
295 {
296         ssize_t r = 0;
297         u8 *p = data;
298 
299         do {
300                 ssize_t ret;
301 
302                 ret = dso_cache_read(dso, machine, offset, p, size);
303                 if (ret < 0)
304                         return ret;
305 
306                 /* Reached EOF, return what we have. */
307                 if (!ret)
308                         break;
309 
310                 BUG_ON(ret > size);
311 
312                 r      += ret;
313                 p      += ret;
314                 offset += ret;
315                 size   -= ret;
316 
317         } while (size);
318 
319         return r;
320 }
321 
322 ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
323                             struct machine *machine, u64 addr,
324                             u8 *data, ssize_t size)
325 {
326         u64 offset = map->map_ip(map, addr);
327         return dso__data_read_offset(dso, machine, offset, data, size);
328 }
329 
330 struct map *dso__new_map(const char *name)
331 {
332         struct map *map = NULL;
333         struct dso *dso = dso__new(name);
334 
335         if (dso)
336                 map = map__new2(0, dso, MAP__FUNCTION);
337 
338         return map;
339 }
340 
341 struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
342                     const char *short_name, int dso_type)
343 {
344         /*
345          * The kernel dso could be created by build_id processing.
346          */
347         struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
348 
349         /*
350          * We need to run this in all cases, since during the build_id
351          * processing we had no idea this was the kernel dso.
352          */
353         if (dso != NULL) {
354                 dso__set_short_name(dso, short_name);
355                 dso->kernel = dso_type;
356         }
357 
358         return dso;
359 }
360 
361 void dso__set_long_name(struct dso *dso, char *name)
362 {
363         if (name == NULL)
364                 return;
365         dso->long_name = name;
366         dso->long_name_len = strlen(name);
367 }
368 
369 void dso__set_short_name(struct dso *dso, const char *name)
370 {
371         if (name == NULL)
372                 return;
373         dso->short_name = name;
374         dso->short_name_len = strlen(name);
375 }
376 
377 static void dso__set_basename(struct dso *dso)
378 {
379         dso__set_short_name(dso, basename(dso->long_name));
380 }
381 
382 int dso__name_len(const struct dso *dso)
383 {
384         if (!dso)
385                 return strlen("[unknown]");
386         if (verbose)
387                 return dso->long_name_len;
388 
389         return dso->short_name_len;
390 }
391 
392 bool dso__loaded(const struct dso *dso, enum map_type type)
393 {
394         return dso->loaded & (1 << type);
395 }
396 
397 bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
398 {
399         return dso->sorted_by_name & (1 << type);
400 }
401 
402 void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
403 {
404         dso->sorted_by_name |= (1 << type);
405 }
406 
407 struct dso *dso__new(const char *name)
408 {
409         struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
410 
411         if (dso != NULL) {
412                 int i;
413                 strcpy(dso->name, name);
414                 dso__set_long_name(dso, dso->name);
415                 dso__set_short_name(dso, dso->name);
416                 for (i = 0; i < MAP__NR_TYPES; ++i)
417                         dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
418                 dso->cache = RB_ROOT;
419                 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
420                 dso->data_type   = DSO_BINARY_TYPE__NOT_FOUND;
421                 dso->loaded = 0;
422                 dso->sorted_by_name = 0;
423                 dso->has_build_id = 0;
424                 dso->kernel = DSO_TYPE_USER;
425                 dso->needs_swap = DSO_SWAP__UNSET;
426                 INIT_LIST_HEAD(&dso->node);
427         }
428 
429         return dso;
430 }
431 
432 void dso__delete(struct dso *dso)
433 {
434         int i;
435         for (i = 0; i < MAP__NR_TYPES; ++i)
436                 symbols__delete(&dso->symbols[i]);
437         if (dso->sname_alloc)
438                 free((char *)dso->short_name);
439         if (dso->lname_alloc)
440                 free(dso->long_name);
441         dso_cache__free(&dso->cache);
442         free(dso);
443 }
444 
445 void dso__set_build_id(struct dso *dso, void *build_id)
446 {
447         memcpy(dso->build_id, build_id, sizeof(dso->build_id));
448         dso->has_build_id = 1;
449 }
450 
451 bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
452 {
453         return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
454 }
455 
456 void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
457 {
458         char path[PATH_MAX];
459 
460         if (machine__is_default_guest(machine))
461                 return;
462         sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
463         if (sysfs__read_build_id(path, dso->build_id,
464                                  sizeof(dso->build_id)) == 0)
465                 dso->has_build_id = true;
466 }
467 
468 int dso__kernel_module_get_build_id(struct dso *dso,
469                                     const char *root_dir)
470 {
471         char filename[PATH_MAX];
472         /*
473          * kernel module short names are of the form "[module]" and
474          * we need just "module" here.
475          */
476         const char *name = dso->short_name + 1;
477 
478         snprintf(filename, sizeof(filename),
479                  "%s/sys/module/%.*s/notes/.note.gnu.build-id",
480                  root_dir, (int)strlen(name) - 1, name);
481 
482         if (sysfs__read_build_id(filename, dso->build_id,
483                                  sizeof(dso->build_id)) == 0)
484                 dso->has_build_id = true;
485 
486         return 0;
487 }
488 
489 bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
490 {
491         bool have_build_id = false;
492         struct dso *pos;
493 
494         list_for_each_entry(pos, head, node) {
495                 if (with_hits && !pos->hit)
496                         continue;
497                 if (pos->has_build_id) {
498                         have_build_id = true;
499                         continue;
500                 }
501                 if (filename__read_build_id(pos->long_name, pos->build_id,
502                                             sizeof(pos->build_id)) > 0) {
503                         have_build_id     = true;
504                         pos->has_build_id = true;
505                 }
506         }
507 
508         return have_build_id;
509 }
510 
511 void dsos__add(struct list_head *head, struct dso *dso)
512 {
513         list_add_tail(&dso->node, head);
514 }
515 
516 struct dso *dsos__find(struct list_head *head, const char *name)
517 {
518         struct dso *pos;
519 
520         list_for_each_entry(pos, head, node)
521                 if (strcmp(pos->long_name, name) == 0)
522                         return pos;
523         return NULL;
524 }
525 
526 struct dso *__dsos__findnew(struct list_head *head, const char *name)
527 {
528         struct dso *dso = dsos__find(head, name);
529 
530         if (!dso) {
531                 dso = dso__new(name);
532                 if (dso != NULL) {
533                         dsos__add(head, dso);
534                         dso__set_basename(dso);
535                 }
536         }
537 
538         return dso;
539 }
540 
541 size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
542                                bool with_hits)
543 {
544         struct dso *pos;
545         size_t ret = 0;
546 
547         list_for_each_entry(pos, head, node) {
548                 if (with_hits && !pos->hit)
549                         continue;
550                 ret += dso__fprintf_buildid(pos, fp);
551                 ret += fprintf(fp, " %s\n", pos->long_name);
552         }
553         return ret;
554 }
555 
556 size_t __dsos__fprintf(struct list_head *head, FILE *fp)
557 {
558         struct dso *pos;
559         size_t ret = 0;
560 
561         list_for_each_entry(pos, head, node) {
562                 int i;
563                 for (i = 0; i < MAP__NR_TYPES; ++i)
564                         ret += dso__fprintf(pos, i, fp);
565         }
566 
567         return ret;
568 }
569 
570 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
571 {
572         char sbuild_id[BUILD_ID_SIZE * 2 + 1];
573 
574         build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
575         return fprintf(fp, "%s", sbuild_id);
576 }
577 
578 size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
579 {
580         struct rb_node *nd;
581         size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
582 
583         if (dso->short_name != dso->long_name)
584                 ret += fprintf(fp, "%s, ", dso->long_name);
585         ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
586                        dso->loaded ? "" : "NOT ");
587         ret += dso__fprintf_buildid(dso, fp);
588         ret += fprintf(fp, ")\n");
589         for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
590                 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
591                 ret += symbol__fprintf(pos, fp);
592         }
593 
594         return ret;
595 }
596 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp