200 likes | 278 Views
Readings on Instrumentation, Profiling, and Tracing. IPT. Seminar presentation by Matthias Hauswirth University of Lugano November 23, 2006. ATOM: A system for building customized program analysis tools. Amitabh Srivastava (MSR) Alan Eustace (Google) PLDI'94. Programs.
E N D
Readings on Instrumentation, Profiling, and Tracing IPT Seminar presentation by Matthias Hauswirth University of Lugano November 23, 2006
ATOM: A system for buildingcustomized program analysis tools Amitabh Srivastava (MSR) Alan Eustace (Google) PLDI'94
Programs Program (linked, statically or dynamically) Module (Object File: .o, .so, .DLL, …) Module (Object File: .o,.so,.DLL, …)
Modules (object files) procedure procedure basic block basic block basic block instr instr instr instr instr instr instr instr instr branch instr branch instr branch instr basic block basic block basic block basic block instr instr instr instr instr instr instr instr instr instr instr instr branch instr branch instr branch instr branch instr
Finding basic blocks(building a control flow graph=CFG) #include <stdio.h> #include <dirent.h> int main(int argc, char* argv[]) { DIR* dir; struct dirent *dp; if ((dir=opendir("/"))==NULL) { perror("Cannot open /"); exit(1); } while ((dp=readdir(dir))!=NULL) { printf("%s\n", dp->d_name); } }
.file "a.c" .section .rodata .LC0: .string "/" .LC1: .string "Cannot open /" .LC2: .string "%s\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp subl $12, %esp pushl $.LC0 call opendir addl $16, %esp movl %eax, -4(%ebp) cmpl $0, -4(%ebp) jne .L3 subl $12, %esp pushl $.LC1 call perror addl $16, %esp subl $12, %esp pushl $1 call exit .L3: subl $12, %esp pushl -4(%ebp) call readdir addl $16, %esp movl %eax, -8(%ebp) cmpl $0, -8(%ebp) je .L4 subl $8, %esp movl -8(%ebp), %eax addl $11, %eax pushl %eax pushl $.LC2 call printf addl $16, %esp jmp .L3 .L4: leave ret .size main, .-main .section .note.GNU-stack,"",@progbits .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-3)"
Dealing with function pointers #include <stdio.h> void f() { printf("f\n"); } void g() { printf("g\n"); } int main(int argc, char* argv[]) { void (*ptf)() = NULL; ptf = g; ptf(); }
.file "b.c" .section .rodata .LC0: .string "f\n" .text .globl f .type f, @function f: pushl %ebp movl %esp, %ebp subl $8, %esp subl $12, %esp pushl $.LC0 call printf addl $16, %esp leave ret .size f, .-f .section .rodata .LC1: .string "g\n" .text .globl g .type g, @function g: pushl %ebp movl %esp, %ebp subl $8, %esp subl $12, %esp pushl $.LC1 call printf addl $16, %esp leave ret .size g, .-g .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp movl $0, -4(%ebp) movl $g, -4(%ebp) movl -4(%ebp), %eax call *%eax leave ret .size main, .-main .section .note.GNU-stack,"",@progbits .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-3)"
Dealing with case statements #include <stdio.h> int main(int argc, char* argv[]) { switch (argc) { case 0: printf("0\n"); case 1: printf("1\n"); break; case 2: printf("2\n"); break; case 3: printf("3\n"); break; case 4: printf("4\n"); break; } }
.file "c.c" .section .rodata .LC0: .string "0\n" .LC1: .string "1\n" .LC2: .string "2\n" .LC3: .string "3\n" .LC4: .string "4\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp cmpl $4, 8(%ebp) ja .L2 movl 8(%ebp), %eax sall $2, %eax movl .L8(%eax), %eax jmp *%eax .section .rodata .align 4 .align 4 .L8: .long .L3 .long .L4 .long .L5 .long .L6 .long .L7 .text .L3: subl $12, %esp pushl $.LC0 call printf addl $16, %esp .L4: subl $12, %esp pushl $.LC1 call printf addl $16, %esp jmp .L2 .L5: subl $12, %esp pushl $.LC2 call printf addl $16, %esp jmp .L2 .L6: subl $12, %esp pushl $.LC3 call printf addl $16, %esp jmp .L2 .L7: subl $12, %esp pushl $.LC4 call printf addl $16, %esp .L2: leave ret .size main, .-main .section .note.GN… .ident "GCC: …
Finding start of basic blocks • 1st instr of a function • 1st instr after a branch instr • Any instr that is the target of a branch instr • Problems • Branches with statically unknown target • Data interleaved with code (e.g. jump tables) • Solutions • Prevent compilers from generating such code • Note • Disassemblers have the same problem
The ATOM process performance analyst application user
Uses of ATOM • Branch profiles • Static branch prediction • Basic block counting • Code coverage • Simulation point determination • Memory reference tracing • Cache/TLB/… simulation • Memory profiling (e.g. for data or code placement, object splitting, …) • Leak detection • Value tracing • Value predictor/… simulation • … (for more, see Figures 5 & 6) • Analysis routines can • Emit traces • Perform analysis online
void Instrument(int argc, char* iargv[]) { Proc* p; Block* b; Inst* inst; int nbranch = 0; AddCallProto(“OpenFile(int)”); AddCallProto(“CondBranch(int,VALUE)”); AddCallProto(“PrintBranch(int,long)”); AddCallProto(“CloseFile()”); for (p=GetFirstProc(); p!=NULL; p=GetNextProc(p)) { for (b=GetFirstblock(); b!=NULL; b=GetNextBlock(b)) { inst=GetLastInst(b); if (isInstType(inst, InstTypeCondBr)){ AddCallInst(inst, InstBefore, “CondBranch”, nbranch, BrCondValue); AddCallProgram(ProgramAfter, “PrintBranch”, nbranch, InstPC(inst)); nbranch++; } } } AddCallProgram(ProgramBefore, “OpenFile”, nbranch); AddCallProgram(ProgramAfter, “CloseFile”); } #include <stdio.h> File* file; struct BranchInfo { long taken; long notTaken; } *bstats; void OpenFile(int n) { bstats = (struct BranchInfo*) malloc(n*sizeof(struct BranchInfo)); file = fopen(“btaken.out”, “w”); fprintf(file, “PC\tTaken\tNot Taken\n”); } void CondBranch(int n, long taken) { if (taken) { bstats[n].taken++; } else { bstats[n].notTaken++; } } void PrintBranch(int n, long pc) { fprintf(file, “0x%lx\t%d\t%d\n”, pc, bstats[n].taken, bstats[n].notTaken); } void CloseFile() { fclose(file); } User Instrumentation Code User Analysis Code
Resulting output (branch profile) PC Taken Not Taken 0x80040ffa 0 1 0x80041004 10 99963 0x8004100a 111 11232 0x8004101f 0 199 0x8004108a 0 1 0x800410af 0 18 0x80041154 0 90 0x80041199 90 90000 0x800411b3 1 0
Minimizing Perturbation addresses of instrumented program != addresses of original program
Slowdown of build process • It takes time to do binary instrumentation • Size of SPEC92 benchmarks • Smallest, 047.tomcatv: 0.1k lines of code • Largest, 085.gcc: 58k lines of code • Gcc is an outlier (next smaller is 15k) • Average (over all BMs) time to instrument • 5.52 … 12.87 sec (depending on tool)
Slowdown of instrumented program 11.84 Critisism: Does not distinguish contributions of ATOM vs. analysis code
Supported platforms • OSF/1 = Tru64 = Digital UNIX on Alpha • Later moved to Windows on IA32 • By TracePoint, a commerical company • I don’t think TracePoint or ATOM is available anywhere today • Other tools: • Vulcan (developed at MSR under Shrivastava) • PIN (developed at Intel, available!) • … (more tools on course web page)
Paper’s impact • One of the most influential PLDI papersin 20 years! • Predecessor of many (most?, all?) similar tools • Sped up research in e.g. hardware design