diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 154 |
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 | ||
32 | static void dso_cache__free(struct rb_root *root); | ||
32 | static bool dso__build_id_equal(const struct dso *dso, u8 *build_id); | 33 | static bool dso__build_id_equal(const struct dso *dso, u8 *build_id); |
33 | static int elf_read_build_id(Elf *elf, void *bf, size_t size); | 34 | static int elf_read_build_id(Elf *elf, void *bf, size_t size); |
34 | static void dsos__add(struct list_head *head, struct dso *dso); | 35 | static 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 | ||
3011 | static ssize_t dso_cache_read(struct dso *dso __used, u64 offset __used, | 3014 | static void |
3012 | u8 *data __used, ssize_t size __used) | 3015 | dso_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 | ||
3017 | static int dso_cache_add(struct dso *dso __used, u64 offset __used, | 3029 | static struct dso_cache* |
3018 | u8 *data __used, ssize_t size __used) | 3030 | dso_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 | |||
3053 | static void | ||
3054 | dso_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 | |||
3078 | static ssize_t | ||
3079 | dso_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 | ||
3023 | static ssize_t read_dso_data(struct dso *dso, struct machine *machine, | 3089 | static ssize_t |
3024 | u64 offset, u8 *data, ssize_t size) | 3090 | dso_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 | |||
3135 | static 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 | ||
3050 | ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, | 3147 | ssize_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 | ||
3058 | ssize_t dso__data_read_addr(struct dso *dso, struct map *map, | 3176 | ssize_t dso__data_read_addr(struct dso *dso, struct map *map, |