[coreboot] Patch set updated: 7700f5d Add support utils for tracing

Rudolf Marek (r.marek@assembler.cz) gerrit at coreboot.org
Sat Sep 3 00:34:35 CEST 2011


Rudolf Marek (r.marek at assembler.cz) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/179

-gerrit

commit 7700f5df07fd80c65eced4deb7d0c6051fd9f2b6
Author: Rudolf Marek <r.marek at assembler.cz>
Date:   Fri Sep 2 23:34:15 2011 +0200

    Add support utils for tracing
    
    Following patch adds a userspace util genprof
    which is able to convert the console printed
    traces to gmon.out file used by gprof & friends.
    The log2dress will replace the adresses in logfile
    with a line numbers.
    
    Change-Id: I9f716f3ff2522a24fbc844a1dd5e32ef49b540c5
    Signed-off-by: Rudolf Marek <r.marek at assembler.cz>
---
 util/genprof/Makefile  |   12 +++++
 util/genprof/README    |   31 ++++++++++++++
 util/genprof/genprof.c |  108 ++++++++++++++++++++++++++++++++++++++++++++++++
 util/genprof/log2dress |   20 +++++++++
 4 files changed, 171 insertions(+), 0 deletions(-)

diff --git a/util/genprof/Makefile b/util/genprof/Makefile
new file mode 100644
index 0000000..2ec77c9
--- /dev/null
+++ b/util/genprof/Makefile
@@ -0,0 +1,12 @@
+CC=gcc
+CFLAGS=-O2 -Wall
+
+all: genprof
+
+genprof: genprof.o
+	$(CC) $(CFLAGS) -o genprof $^
+
+clean:
+	rm -f genprof  *.o *~
+
+distclean: clean
diff --git a/util/genprof/README b/util/genprof/README
new file mode 100644
index 0000000..3483a2b
--- /dev/null
+++ b/util/genprof/README
@@ -0,0 +1,31 @@
+Function tracing
+----------------
+
+Enable CONFIG_TRACE in debug menu. Run the compiled image on target. You will get
+a log with a lot of lines like:
+
+...
+~0x001072e8(0x00100099)
+~0x00108bc0(0x0010730a)
+...
+
+First address is address of function which was just entered, the second address
+is address of functions which call that.
+
+You can use the log2dress to dress the log again:
+
+...
+src/arch/x86/lib/c_start.S:85 calls /home/ruik/coreboot/src/boot/selfboot.c:367
+/home/ruik/coreboot/src/boot/selfboot.c:370 calls /home/ruik/coreboot/src/devices/device.c:325
+...
+
+Alternatively, you can use genprof to generate a gmon.out file, which can be used
+by gprof to show the call traces. You will need to install uthash library to compile
+that.
+
+Great use is:
+
+make
+./genprof /tmp/yourlog ;  gprof ../../build/coreboot_ram |  ./gprof2dot.py -e0 -n0 | dot -Tpng -o output.png
+
+Which generates a PNG with a call graph.
diff --git a/util/genprof/genprof.c b/util/genprof/genprof.c
new file mode 100644
index 0000000..9fc39da
--- /dev/null
+++ b/util/genprof/genprof.c
@@ -0,0 +1,108 @@
+#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");
+	fo = fopen("gmon.out", "w+");
+
+	if ((f == NULL) || (fo == NULL)) {
+		fprintf(stderr, "Unable to manipulate with the input file\n");
+		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);
+	return 0;
+}
diff --git a/util/genprof/log2dress b/util/genprof/log2dress
new file mode 100755
index 0000000..429f846
--- /dev/null
+++ b/util/genprof/log2dress
@@ -0,0 +1,20 @@
+#!/bin/bash
+#Parse a log and get back the function names and line numbers
+#Provide a log file as first argument
+
+#Please rewrite to something more saner !
+
+cat $1 | while read line ; do
+A=`echo $line | cut -c 1`
+
+if [ "$A" = '~' ] ; then
+FROM=`echo $line | tr \~ \( | tr \) \(  | awk -F\( '{print $3}'`
+TO=`echo $line  | tr \~ \( | tr \) \(|awk -F\( '{print $2}'`
+addr2line -e ../../build/coreboot_ram.debug "$FROM" | tr -d "\n"
+echo -n " calls "
+addr2line -e ../../build/coreboot_ram.debug "$TO"
+else
+echo "$line"
+fi
+
+done




More information about the coreboot mailing list