2 * Simple naive instrumentation on (x86) assembler files
3 * @author Matthias Braun (warning this is a 30 minutes hack and no nice code!)
5 * Takes an assembler file and adds instrumentation code to some instructions.
6 * You have to link the output with saveinstr.c
8 * Example usage with a file queens.s:
10 * (adapt is_instr function here to your needs and compile instrument.cpp)
11 * instrument < queens.s > queensi.s
12 * gcc queensi.s saveinstr.c -o queensi
13 * ./queensi (run with you desired arguments and testdata)
14 * instrument -a < queens.s > queens_annotated.s
15 * You will get a list of the hottest spots in your file and an assembler
16 * will the instructions prefixed with their execution count
26 /** checks if we have an instruction that should be instrumented */
27 bool is_instr(const char* str)
35 if(str[1] == 'c' && str[2] == 'a' && str[3] == 'l')
49 bool operator <(const place& other) const
51 return count > other.count;
55 int main(int argc, char** argv)
59 bool annotate = false;
60 std::vector<place> places;
67 if(argc == 2 && std::string(argv[1]) == "-a") {
69 instr = fopen("instr.out", "r");
70 assert(instr != NULL);
74 fgets(linebuf, sizeof(linebuf), file);
79 if(is_instr(linebuf)) {
83 assert(fread(&p.count, 4, 1, instr) == 1);
84 printf("/* %u */ ", p.count);
89 printf("\tinc DWORD PTR[__instr + %d]\n", (instrcount++) * 4);
94 printf("%s", linebuf);
97 if(strcmp(linebuf, "main:\n") == 0) {
98 printf("\tsub %%esp, 4\n"
99 "\tmov DWORD PTR[%%esp], OFFSET FLAT:__saveinstr\n"
107 printf("\n\t.section .bss\n"
111 ".global __instrend\n"
112 "__instrend:\n", instrcount * 4);
114 std::sort(places.begin(), places.end());
116 for(int i = 0; i < 20 && i < places.size(); ++i) {
117 const place &p = places[i];
118 fprintf(stderr, "line %d: %u\n", p.line, p.count);