aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c154
1 files changed, 136 insertions, 18 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 8131949d10f..fdad4eeeb42 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -29,6 +29,7 @@
29#define NT_GNU_BUILD_ID 3 29#define NT_GNU_BUILD_ID 3
30#endif 30#endif
31 31
32static void dso_cache__free(struct rb_root *root);
32static bool dso__build_id_equal(const struct dso *dso, u8 *build_id); 33static bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
33static int elf_read_build_id(Elf *elf, void *bf, size_t size); 34static int elf_read_build_id(Elf *elf, void *bf, size_t size);
34static void dsos__add(struct list_head *head, struct dso *dso); 35static void dsos__add(struct list_head *head, struct dso *dso);
@@ -343,6 +344,7 @@ struct dso *dso__new(const char *name)
343 dso__set_short_name(dso, dso->name); 344 dso__set_short_name(dso, dso->name);
344 for (i = 0; i < MAP__NR_TYPES; ++i) 345 for (i = 0; i < MAP__NR_TYPES; ++i)
345 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; 346 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
347 dso->cache = RB_ROOT;
346 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; 348 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
347 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND; 349 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
348 dso->loaded = 0; 350 dso->loaded = 0;
@@ -378,6 +380,7 @@ void dso__delete(struct dso *dso)
378 free((char *)dso->short_name); 380 free((char *)dso->short_name);
379 if (dso->lname_alloc) 381 if (dso->lname_alloc)
380 free(dso->long_name); 382 free(dso->long_name);
383 dso_cache__free(&dso->cache);
381 free(dso); 384 free(dso);
382} 385}
383 386
@@ -3008,22 +3011,87 @@ int dso__data_fd(struct dso *dso, struct machine *machine)
3008 return -EINVAL; 3011 return -EINVAL;
3009} 3012}
3010 3013
3011static ssize_t dso_cache_read(struct dso *dso __used, u64 offset __used, 3014static void
3012 u8 *data __used, ssize_t size __used) 3015dso_cache__free(struct rb_root *root)
3013{ 3016{
3014 return -EINVAL; 3017 struct rb_node *next = rb_first(root);
3018
3019 while (next) {
3020 struct dso_cache *cache;
3021
3022 cache = rb_entry(next, struct dso_cache, rb_node);
3023 next = rb_next(&cache->rb_node);
3024 rb_erase(&cache->rb_node, root);
3025 free(cache);
3026 }
3015} 3027}
3016 3028
3017static int dso_cache_add(struct dso *dso __used, u64 offset __used, 3029static struct dso_cache*
3018 u8 *data __used, ssize_t size __used) 3030dso_cache__find(struct rb_root *root, u64 offset)
3019{ 3031{
3020 return 0; 3032 struct rb_node **p = &root->rb_node;
3033 struct rb_node *parent = NULL;
3034 struct dso_cache *cache;
3035
3036 while (*p != NULL) {
3037 u64 end;
3038
3039 parent = *p;
3040 cache = rb_entry(parent, struct dso_cache, rb_node);
3041 end = cache->offset + DSO__DATA_CACHE_SIZE;
3042
3043 if (offset < cache->offset)
3044 p = &(*p)->rb_left;
3045 else if (offset >= end)
3046 p = &(*p)->rb_right;
3047 else
3048 return cache;
3049 }
3050 return NULL;
3051}
3052
3053static void
3054dso_cache__insert(struct rb_root *root, struct dso_cache *new)
3055{
3056 struct rb_node **p = &root->rb_node;
3057 struct rb_node *parent = NULL;
3058 struct dso_cache *cache;
3059 u64 offset = new->offset;
3060
3061 while (*p != NULL) {
3062 u64 end;
3063
3064 parent = *p;
3065 cache = rb_entry(parent, struct dso_cache, rb_node);
3066 end = cache->offset + DSO__DATA_CACHE_SIZE;
3067
3068 if (offset < cache->offset)
3069 p = &(*p)->rb_left;
3070 else if (offset >= end)
3071 p = &(*p)->rb_right;
3072 }
3073
3074 rb_link_node(&new->rb_node, parent, p);
3075 rb_insert_color(&new->rb_node, root);
3076}
3077
3078static ssize_t
3079dso_cache__memcpy(struct dso_cache *cache, u64 offset,
3080 u8 *data, u64 size)
3081{
3082 u64 cache_offset = offset - cache->offset;
3083 u64 cache_size = min(cache->size - cache_offset, size);
3084
3085 memcpy(data, cache->data + cache_offset, cache_size);
3086 return cache_size;
3021} 3087}
3022 3088
3023static ssize_t read_dso_data(struct dso *dso, struct machine *machine, 3089static ssize_t
3024 u64 offset, u8 *data, ssize_t size) 3090dso_cache__read(struct dso *dso, struct machine *machine,
3091 u64 offset, u8 *data, ssize_t size)
3025{ 3092{
3026 ssize_t rsize = -1; 3093 struct dso_cache *cache;
3094 ssize_t ret;
3027 int fd; 3095 int fd;
3028 3096
3029 fd = dso__data_fd(dso, machine); 3097 fd = dso__data_fd(dso, machine);
@@ -3031,28 +3099,78 @@ static ssize_t read_dso_data(struct dso *dso, struct machine *machine,
3031 return -1; 3099 return -1;
3032 3100
3033 do { 3101 do {
3034 if (-1 == lseek(fd, offset, SEEK_SET)) 3102 u64 cache_offset;
3103
3104 ret = -ENOMEM;
3105
3106 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
3107 if (!cache)
3035 break; 3108 break;
3036 3109
3037 rsize = read(fd, data, size); 3110 cache_offset = offset & DSO__DATA_CACHE_MASK;
3038 if (-1 == rsize) 3111 ret = -EINVAL;
3112
3113 if (-1 == lseek(fd, cache_offset, SEEK_SET))
3039 break; 3114 break;
3040 3115
3041 if (dso_cache_add(dso, offset, data, size)) 3116 ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
3042 pr_err("Failed to add data int dso cache."); 3117 if (ret <= 0)
3118 break;
3119
3120 cache->offset = cache_offset;
3121 cache->size = ret;
3122 dso_cache__insert(&dso->cache, cache);
3123
3124 ret = dso_cache__memcpy(cache, offset, data, size);
3043 3125
3044 } while (0); 3126 } while (0);
3045 3127
3128 if (ret <= 0)
3129 free(cache);
3130
3046 close(fd); 3131 close(fd);
3047 return rsize; 3132 return ret;
3133}
3134
3135static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
3136 u64 offset, u8 *data, ssize_t size)
3137{
3138 struct dso_cache *cache;
3139
3140 cache = dso_cache__find(&dso->cache, offset);
3141 if (cache)
3142 return dso_cache__memcpy(cache, offset, data, size);
3143 else
3144 return dso_cache__read(dso, machine, offset, data, size);
3048} 3145}
3049 3146
3050ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, 3147ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
3051 u64 offset, u8 *data, ssize_t size) 3148 u64 offset, u8 *data, ssize_t size)
3052{ 3149{
3053 if (dso_cache_read(dso, offset, data, size)) 3150 ssize_t r = 0;
3054 return read_dso_data(dso, machine, offset, data, size); 3151 u8 *p = data;
3055 return 0; 3152
3153 do {
3154 ssize_t ret;
3155
3156 ret = dso_cache_read(dso, machine, offset, p, size);
3157 if (ret < 0)
3158 return ret;
3159
3160 /* Reached EOF, return what we have. */
3161 if (!ret)
3162 break;
3163
3164 BUG_ON(ret > size);
3165
3166 r += ret;
3167 p += ret;
3168 offset += ret;
3169 size -= ret;
3170
3171 } while (size);
3172
3173 return r;
3056} 3174}
3057 3175
3058ssize_t dso__data_read_addr(struct dso *dso, struct map *map, 3176ssize_t dso__data_read_addr(struct dso *dso, struct map *map,