Accept only one command line argument (the input file name); close input stream both on error and on success; print more informative error messages when files could not be opened. Change-Id: Ib2f0622a332317d7a13f33f1e5787381804c43a9 Found-by: missing fclose()'s found by Cppcheck 1.65 Signed-off-by: Daniele Forsi <dforsi@gmail.com> Reviewed-on: http://review.coreboot.org/6573 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
		
			
				
	
	
		
			115 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <stdio.h>
 | |
| #include <uthash.h>
 | |
| #include <sys/gmon_out.h>
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #define GMON_SEC "seconds        s"
 | |
| uint32_t mineip = 0xffffffff;
 | |
| uint32_t maxeip = 0;
 | |
| 
 | |
| /* a hash structure to hold the arc */
 | |
| struct arec {
 | |
| 	uint32_t eip;
 | |
| 	uint32_t from;
 | |
| 	uint32_t count;
 | |
| 	UT_hash_handle hh;
 | |
| };
 | |
| 
 | |
| struct arec *arc = NULL;
 | |
| 
 | |
| void note_arc(uint32_t eip, uint32_t from)
 | |
| {
 | |
| 	struct arec *s;
 | |
| 
 | |
| 	HASH_FIND_INT(arc, &eip, s);
 | |
| 	if (s == NULL) {
 | |
| 		s = malloc(sizeof(struct arec));
 | |
| 		s->eip = eip;
 | |
| 		s->from = from;
 | |
| 		s->count = 1;
 | |
| 		if (eip > maxeip)
 | |
| 			maxeip = eip;
 | |
| 		if (eip < mineip)
 | |
| 			maxeip = eip;
 | |
| 
 | |
| 		HASH_ADD_INT(arc, eip, s);
 | |
| 	} else {
 | |
| 		s->count++;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int main(int argc, char* argv[])
 | |
| {
 | |
| 	FILE *f, *fo;
 | |
| 	struct arec *s;
 | |
| 	uint32_t eip, from, tmp;
 | |
| 	uint8_t tag;
 | |
| 	uint16_t hit;
 | |
| 
 | |
| 	if (argc != 2) {
 | |
| 		fprintf(stderr, "Please specify the coreboot trace log as parameter\n");
 | |
| 		return 1;
 | |
| 	}
 | |
| 
 | |
| 	f = fopen(argv[1], "r");
 | |
| 	if (f == NULL) {
 | |
| 		perror("Unable to open the input file");
 | |
| 		return 1;
 | |
| 	}
 | |
| 
 | |
| 	fo = fopen("gmon.out", "w+");
 | |
| 	if (fo == NULL) {
 | |
| 		perror("Unable to open the output file");
 | |
| 		fclose(f);
 | |
| 		return 1;
 | |
| 	}
 | |
| 
 | |
| 	while (!feof(f)) {
 | |
| 		if (fscanf(f, "~%x(%x)%*[^\n]\n", &eip, &from) == 2) {
 | |
| 			note_arc(eip, from);
 | |
| 		} else if (fscanf(f, "%*c~%x(%x)%*[^\n]\n", &eip, &from) == 2) {
 | |
| 			note_arc(eip, from);
 | |
| 		} else {
 | |
| 			/* just drop a line */
 | |
| 			tmp = fscanf(f, "%*[^\n]\n");
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* write gprof header */
 | |
| 	fwrite(GMON_MAGIC, 1, sizeof(GMON_MAGIC) - 1, fo);
 | |
| 	tmp = GMON_VERSION;
 | |
| 	fwrite(&tmp, 1, sizeof(tmp), fo);
 | |
| 	tmp = 0;
 | |
| 	fwrite(&tmp, 1, sizeof(tmp), fo);
 | |
| 	fwrite(&tmp, 1, sizeof(tmp), fo);
 | |
| 	fwrite(&tmp, 1, sizeof(tmp), fo);
 | |
| 	/* write fake histogram */
 | |
| 	tag = GMON_TAG_TIME_HIST;
 | |
| 	fwrite(&tag, 1, sizeof(tag), fo);
 | |
| 	fwrite(&mineip, 1, sizeof(mineip), fo);
 | |
| 	fwrite(&maxeip, 1, sizeof(maxeip), fo);
 | |
| 	/* size of histogram */
 | |
| 	tmp = 1;
 | |
| 	fwrite(&tmp, 1, sizeof(tmp), fo);
 | |
| 	/* prof rate */
 | |
| 	tmp = 1000;
 | |
| 	fwrite(&tmp, 1, sizeof(tmp), fo);
 | |
| 	fwrite(GMON_SEC, 1, sizeof(GMON_SEC) - 1, fo);
 | |
| 	hit = 1;
 | |
| 	fwrite(&hit, 1, sizeof(hit), fo);
 | |
| 
 | |
| 	/* write call graph data */
 | |
| 	tag = GMON_TAG_CG_ARC;
 | |
| 	for (s = arc; s != NULL; s = s->hh.next) {
 | |
| 		fwrite(&tag, 1, sizeof(tag), fo);
 | |
| 		fwrite(&s->from, 1, sizeof(s->from), fo);
 | |
| 		fwrite(&s->eip, 1, sizeof(s->eip), fo);
 | |
| 		fwrite(&s->count, 1, sizeof(s->count), fo);
 | |
| 	}
 | |
| 
 | |
| 	fclose(fo);
 | |
| 	fclose(f);
 | |
| 
 | |
| 	return 0;
 | |
| }
 |