1/* 2 * This code provides functions to handle gcc's profiling data format 3 * introduced with gcc 3.4. Future versions of gcc may change the gcov 4 * format (as happened before), so all format-specific information needs 5 * to be kept modular and easily exchangeable. 6 * 7 * This file is based on gcc-internal definitions. Functions and data 8 * structures are defined to be compatible with gcc counterparts. 9 * For a better understanding, refer to gcc source: gcc/gcov-io.h. 10 * 11 * Copyright IBM Corp. 2009 12 * Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com> 13 * 14 * Uses gcc-internal data definitions. 15 */ 16 17#include <linux/errno.h> 18#include <linux/slab.h> 19#include <linux/string.h> 20#include <linux/seq_file.h> 21#include <linux/vmalloc.h> 22#include "gcov.h" 23 24/* Symbolic links to be created for each profiling data file. */ 25const struct gcov_link gcov_link[] = { 26 { OBJ_TREE, "gcno" }, /* Link to .gcno file in $(objtree). */ 27 { 0, NULL}, 28}; 29 30/* 31 * Determine whether a counter is active. Based on gcc magic. Doesn't change 32 * at run-time. 33 */ 34static int counter_active(struct gcov_info *info, unsigned int type) 35{ 36 return (1 << type) & info->ctr_mask; 37} 38 39/* Determine number of active counters. Based on gcc magic. */ 40static unsigned int num_counter_active(struct gcov_info *info) 41{ 42 unsigned int i; 43 unsigned int result = 0; 44 45 for (i = 0; i < GCOV_COUNTERS; i++) { 46 if (counter_active(info, i)) 47 result++; 48 } 49 return result; 50} 51 52/** 53 * gcov_info_reset - reset profiling data to zero 54 * @info: profiling data set 55 */ 56void gcov_info_reset(struct gcov_info *info) 57{ 58 unsigned int active = num_counter_active(info); 59 unsigned int i; 60 61 for (i = 0; i < active; i++) { 62 memset(info->counts[i].values, 0, 63 info->counts[i].num * sizeof(gcov_type)); 64 } 65} 66 67/** 68 * gcov_info_is_compatible - check if profiling data can be added 69 * @info1: first profiling data set 70 * @info2: second profiling data set 71 * 72 * Returns non-zero if profiling data can be added, zero otherwise. 73 */ 74int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2) 75{ 76 return (info1->stamp == info2->stamp); 77} 78 79/** 80 * gcov_info_add - add up profiling data 81 * @dest: profiling data set to which data is added 82 * @source: profiling data set which is added 83 * 84 * Adds profiling counts of @source to @dest. 85 */ 86void gcov_info_add(struct gcov_info *dest, struct gcov_info *source) 87{ 88 unsigned int i; 89 unsigned int j; 90 91 for (i = 0; i < num_counter_active(dest); i++) { 92 for (j = 0; j < dest->counts[i].num; j++) { 93 dest->counts[i].values[j] += 94 source->counts[i].values[j]; 95 } 96 } 97} 98 99/* Get size of function info entry. Based on gcc magic. */ 100static size_t get_fn_size(struct gcov_info *info) 101{ 102 size_t size; 103 104 size = sizeof(struct gcov_fn_info) + num_counter_active(info) * 105 sizeof(unsigned int); 106 if (__alignof__(struct gcov_fn_info) > sizeof(unsigned int)) 107 size = ALIGN(size, __alignof__(struct gcov_fn_info)); 108 return size; 109} 110 111/* Get address of function info entry. Based on gcc magic. */ 112static struct gcov_fn_info *get_fn_info(struct gcov_info *info, unsigned int fn) 113{ 114 return (struct gcov_fn_info *) 115 ((char *) info->functions + fn * get_fn_size(info)); 116} 117 118/** 119 * gcov_info_dup - duplicate profiling data set 120 * @info: profiling data set to duplicate 121 * 122 * Return newly allocated duplicate on success, %NULL on error. 123 */ 124struct gcov_info *gcov_info_dup(struct gcov_info *info) 125{ 126 struct gcov_info *dup; 127 unsigned int i; 128 unsigned int active; 129 130 /* Duplicate gcov_info. */ 131 active = num_counter_active(info); 132 dup = kzalloc(sizeof(struct gcov_info) + 133 sizeof(struct gcov_ctr_info) * active, GFP_KERNEL); 134 if (!dup) 135 return NULL; 136 dup->version = info->version; 137 dup->stamp = info->stamp; 138 dup->n_functions = info->n_functions; 139 dup->ctr_mask = info->ctr_mask; 140 /* Duplicate filename. */ 141 dup->filename = kstrdup(info->filename, GFP_KERNEL); 142 if (!dup->filename) 143 goto err_free; 144 /* Duplicate table of functions. */ 145 dup->functions = kmemdup(info->functions, info->n_functions * 146 get_fn_size(info), GFP_KERNEL); 147 if (!dup->functions) 148 goto err_free; 149 /* Duplicate counter arrays. */ 150 for (i = 0; i < active ; i++) { 151 struct gcov_ctr_info *ctr = &info->counts[i]; 152 size_t size = ctr->num * sizeof(gcov_type); 153 154 dup->counts[i].num = ctr->num; 155 dup->counts[i].merge = ctr->merge; 156 dup->counts[i].values = vmalloc(size); 157 if (!dup->counts[i].values) 158 goto err_free; 159 memcpy(dup->counts[i].values, ctr->values, size); 160 } 161 return dup; 162 163err_free: 164 gcov_info_free(dup); 165 return NULL; 166} 167 168/** 169 * gcov_info_free - release memory for profiling data set duplicate 170 * @info: profiling data set duplicate to free 171 */ 172void gcov_info_free(struct gcov_info *info) 173{ 174 unsigned int active = num_counter_active(info); 175 unsigned int i; 176 177 for (i = 0; i < active ; i++) 178 vfree(info->counts[i].values); 179 kfree(info->functions); 180 kfree(info->filename); 181 kfree(info); 182} 183 184/** 185 * struct type_info - iterator helper array 186 * @ctr_type: counter type 187 * @offset: index of the first value of the current function for this type 188 * 189 * This array is needed to convert the in-memory data format into the in-file 190 * data format: 191 * 192 * In-memory: 193 * for each counter type 194 * for each function 195 * values 196 * 197 * In-file: 198 * for each function 199 * for each counter type 200 * values 201 * 202 * See gcc source gcc/gcov-io.h for more information on data organization. 203 */ 204struct type_info { 205 int ctr_type; 206 unsigned int offset; 207}; 208 209/** 210 * struct gcov_iterator - specifies current file position in logical records 211 * @info: associated profiling data 212 * @record: record type 213 * @function: function number 214 * @type: counter type 215 * @count: index into values array 216 * @num_types: number of counter types 217 * @type_info: helper array to get values-array offset for current function 218 */ 219struct gcov_iterator { 220 struct gcov_info *info; 221 222 int record; 223 unsigned int function; 224 unsigned int type; 225 unsigned int count; 226 227 int num_types; 228 struct type_info type_info[0]; 229}; 230 231static struct gcov_fn_info *get_func(struct gcov_iterator *iter) 232{ 233 return get_fn_info(iter->info, iter->function); 234} 235 236static struct type_info *get_type(struct gcov_iterator *iter) 237{ 238 return &iter->type_info[iter->type]; 239} 240 241/** 242 * gcov_iter_new - allocate and initialize profiling data iterator 243 * @info: profiling data set to be iterated 244 * 245 * Return file iterator on success, %NULL otherwise. 246 */ 247struct gcov_iterator *gcov_iter_new(struct gcov_info *info) 248{ 249 struct gcov_iterator *iter; 250 251 iter = kzalloc(sizeof(struct gcov_iterator) + 252 num_counter_active(info) * sizeof(struct type_info), 253 GFP_KERNEL); 254 if (iter) 255 iter->info = info; 256 257 return iter; 258} 259 260/** 261 * gcov_iter_free - release memory for iterator 262 * @iter: file iterator to free 263 */ 264void gcov_iter_free(struct gcov_iterator *iter) 265{ 266 kfree(iter); 267} 268 269/** 270 * gcov_iter_get_info - return profiling data set for given file iterator 271 * @iter: file iterator 272 */ 273struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter) 274{ 275 return iter->info; 276} 277 278/** 279 * gcov_iter_start - reset file iterator to starting position 280 * @iter: file iterator 281 */ 282void gcov_iter_start(struct gcov_iterator *iter) 283{ 284 int i; 285 286 iter->record = 0; 287 iter->function = 0; 288 iter->type = 0; 289 iter->count = 0; 290 iter->num_types = 0; 291 for (i = 0; i < GCOV_COUNTERS; i++) { 292 if (counter_active(iter->info, i)) { 293 iter->type_info[iter->num_types].ctr_type = i; 294 iter->type_info[iter->num_types++].offset = 0; 295 } 296 } 297} 298 299/* Mapping of logical record number to actual file content. */ 300#define RECORD_FILE_MAGIC 0 301#define RECORD_GCOV_VERSION 1 302#define RECORD_TIME_STAMP 2 303#define RECORD_FUNCTION_TAG 3 304#define RECORD_FUNCTON_TAG_LEN 4 305#define RECORD_FUNCTION_IDENT 5 306#define RECORD_FUNCTION_CHECK 6 307#define RECORD_COUNT_TAG 7 308#define RECORD_COUNT_LEN 8 309#define RECORD_COUNT 9 310 311/** 312 * gcov_iter_next - advance file iterator to next logical record 313 * @iter: file iterator 314 * 315 * Return zero if new position is valid, non-zero if iterator has reached end. 316 */ 317int gcov_iter_next(struct gcov_iterator *iter) 318{ 319 switch (iter->record) { 320 case RECORD_FILE_MAGIC: 321 case RECORD_GCOV_VERSION: 322 case RECORD_FUNCTION_TAG: 323 case RECORD_FUNCTON_TAG_LEN: 324 case RECORD_FUNCTION_IDENT: 325 case RECORD_COUNT_TAG: 326 /* Advance to next record */ 327 iter->record++; 328 break; 329 case RECORD_COUNT: 330 /* Advance to next count */ 331 iter->count++; 332 /* fall through */ 333 case RECORD_COUNT_LEN: 334 if (iter->count < get_func(iter)->n_ctrs[iter->type]) { 335 iter->record = 9; 336 break; 337 } 338 /* Advance to next counter type */ 339 get_type(iter)->offset += iter->count; 340 iter->count = 0; 341 iter->type++; 342 /* fall through */ 343 case RECORD_FUNCTION_CHECK: 344 if (iter->type < iter->num_types) { 345 iter->record = 7; 346 break; 347 } 348 /* Advance to next function */ 349 iter->type = 0; 350 iter->function++; 351 /* fall through */ 352 case RECORD_TIME_STAMP: 353 if (iter->function < iter->info->n_functions) 354 iter->record = 3; 355 else 356 iter->record = -1; 357 break; 358 } 359 /* Check for EOF. */ 360 if (iter->record == -1) 361 return -EINVAL; 362 else 363 return 0; 364} 365 366/** 367 * seq_write_gcov_u32 - write 32 bit number in gcov format to seq_file 368 * @seq: seq_file handle 369 * @v: value to be stored 370 * 371 * Number format defined by gcc: numbers are recorded in the 32 bit 372 * unsigned binary form of the endianness of the machine generating the 373 * file. 374 */ 375static int seq_write_gcov_u32(struct seq_file *seq, u32 v) 376{ 377 return seq_write(seq, &v, sizeof(v)); 378} 379 380/** 381 * seq_write_gcov_u64 - write 64 bit number in gcov format to seq_file 382 * @seq: seq_file handle 383 * @v: value to be stored 384 * 385 * Number format defined by gcc: numbers are recorded in the 32 bit 386 * unsigned binary form of the endianness of the machine generating the 387 * file. 64 bit numbers are stored as two 32 bit numbers, the low part 388 * first. 389 */ 390static int seq_write_gcov_u64(struct seq_file *seq, u64 v) 391{ 392 u32 data[2]; 393 394 data[0] = (v & 0xffffffffUL); 395 data[1] = (v >> 32); 396 return seq_write(seq, data, sizeof(data)); 397} 398 399/** 400 * gcov_iter_write - write data for current pos to seq_file 401 * @iter: file iterator 402 * @seq: seq_file handle 403 * 404 * Return zero on success, non-zero otherwise. 405 */ 406int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq) 407{ 408 int rc = -EINVAL; 409 410 switch (iter->record) { 411 case RECORD_FILE_MAGIC: 412 rc = seq_write_gcov_u32(seq, GCOV_DATA_MAGIC); 413 break; 414 case RECORD_GCOV_VERSION: 415 rc = seq_write_gcov_u32(seq, iter->info->version); 416 break; 417 case RECORD_TIME_STAMP: 418 rc = seq_write_gcov_u32(seq, iter->info->stamp); 419 break; 420 case RECORD_FUNCTION_TAG: 421 rc = seq_write_gcov_u32(seq, GCOV_TAG_FUNCTION); 422 break; 423 case RECORD_FUNCTON_TAG_LEN: 424 rc = seq_write_gcov_u32(seq, 2); 425 break; 426 case RECORD_FUNCTION_IDENT: 427 rc = seq_write_gcov_u32(seq, get_func(iter)->ident); 428 break; 429 case RECORD_FUNCTION_CHECK: 430 rc = seq_write_gcov_u32(seq, get_func(iter)->checksum); 431 break; 432 case RECORD_COUNT_TAG: 433 rc = seq_write_gcov_u32(seq, 434 GCOV_TAG_FOR_COUNTER(get_type(iter)->ctr_type)); 435 break; 436 case RECORD_COUNT_LEN: 437 rc = seq_write_gcov_u32(seq, 438 get_func(iter)->n_ctrs[iter->type] * 2); 439 break; 440 case RECORD_COUNT: 441 rc = seq_write_gcov_u64(seq, 442 iter->info->counts[iter->type]. 443 values[iter->count + get_type(iter)->offset]); 444 break; 445 } 446 return rc; 447} 448