1*62aa74f8SRafael Auler //===-- instr.cpp -----------------------------------------------*- C++ -*-===// 2*62aa74f8SRafael Auler // 3*62aa74f8SRafael Auler // The LLVM Compiler Infrastructure 4*62aa74f8SRafael Auler // 5*62aa74f8SRafael Auler // This file is distributed under the University of Illinois Open Source 6*62aa74f8SRafael Auler // License. See LICENSE.TXT for details. 7*62aa74f8SRafael Auler // This file contains code that is linked to the final binary with a function 8*62aa74f8SRafael Auler // that is called at program exit to dump instrumented data collected during 9*62aa74f8SRafael Auler // execution. 10*62aa74f8SRafael Auler // 11*62aa74f8SRafael Auler //===----------------------------------------------------------------------===// 12*62aa74f8SRafael Auler // 13*62aa74f8SRafael Auler // BOLT runtime instrumentation library. 14*62aa74f8SRafael Auler // 15*62aa74f8SRafael Auler //===----------------------------------------------------------------------===// 16*62aa74f8SRafael Auler 17*62aa74f8SRafael Auler #include <cstdint> 18*62aa74f8SRafael Auler 19*62aa74f8SRafael Auler // All extern declarations here need to be defined by BOLT itself. 20*62aa74f8SRafael Auler 21*62aa74f8SRafael Auler // Counters inserted by instrumentation, incremented during runtime when 22*62aa74f8SRafael Auler // points of interest (locations) in the program are reached. 23*62aa74f8SRafael Auler extern uint64_t __bolt_instr_locations[]; 24*62aa74f8SRafael Auler // Number of counters. 25*62aa74f8SRafael Auler extern uint32_t __bolt_instr_num_locs; 26*62aa74f8SRafael Auler // String table with function names. 27*62aa74f8SRafael Auler extern char __bolt_instr_strings[]; 28*62aa74f8SRafael Auler // Filename to dump data to. 29*62aa74f8SRafael Auler extern char __bolt_instr_filename[]; 30*62aa74f8SRafael Auler 31*62aa74f8SRafael Auler // A location is a function name plus offset. Function name needs to be 32*62aa74f8SRafael Auler // retrieved from the string table and is stored as an index to this table. 33*62aa74f8SRafael Auler typedef struct _Location { 34*62aa74f8SRafael Auler uint32_t FunctionName; 35*62aa74f8SRafael Auler uint32_t Offset; 36*62aa74f8SRafael Auler } Location; 37*62aa74f8SRafael Auler 38*62aa74f8SRafael Auler // An edge description defines an instrumented edge in the program, fully 39*62aa74f8SRafael Auler // identified by where the jump is located and its destination. 40*62aa74f8SRafael Auler typedef struct _EdgeDescription { 41*62aa74f8SRafael Auler Location From; 42*62aa74f8SRafael Auler Location To; 43*62aa74f8SRafael Auler } EdgeDescription; 44*62aa74f8SRafael Auler 45*62aa74f8SRafael Auler extern EdgeDescription __bolt_instr_descriptions[]; 46*62aa74f8SRafael Auler 47*62aa74f8SRafael Auler // Declare some syscall wrappers we use throughout this code to avoid linking 48*62aa74f8SRafael Auler // against system libc. 49*62aa74f8SRafael Auler static uint64_t 50*62aa74f8SRafael Auler myopen(const char *pathname, 51*62aa74f8SRafael Auler uint64_t flags, 52*62aa74f8SRafael Auler uint64_t mode) { 53*62aa74f8SRafael Auler uint64_t ret; 54*62aa74f8SRafael Auler __asm__ __volatile__ ( 55*62aa74f8SRafael Auler "movq $2, %%rax\n" 56*62aa74f8SRafael Auler "syscall" 57*62aa74f8SRafael Auler : "=a"(ret) 58*62aa74f8SRafael Auler : "D"(pathname), "S"(flags), "d"(mode) 59*62aa74f8SRafael Auler : "cc", "rcx", "r11", "memory"); 60*62aa74f8SRafael Auler return ret; 61*62aa74f8SRafael Auler } 62*62aa74f8SRafael Auler 63*62aa74f8SRafael Auler static uint64_t mywrite(uint64_t fd, const void *buf, uint64_t count) { 64*62aa74f8SRafael Auler uint64_t ret; 65*62aa74f8SRafael Auler __asm__ __volatile__ ( 66*62aa74f8SRafael Auler "movq $1, %%rax\n" 67*62aa74f8SRafael Auler "syscall\n" 68*62aa74f8SRafael Auler : "=a"(ret) 69*62aa74f8SRafael Auler : "D"(fd), "S"(buf), "d"(count) 70*62aa74f8SRafael Auler : "cc", "rcx", "r11", "memory"); 71*62aa74f8SRafael Auler return ret; 72*62aa74f8SRafael Auler } 73*62aa74f8SRafael Auler 74*62aa74f8SRafael Auler static int myclose(uint64_t fd) { 75*62aa74f8SRafael Auler uint64_t ret; 76*62aa74f8SRafael Auler __asm__ __volatile__ ( 77*62aa74f8SRafael Auler "movq $3, %%rax\n" 78*62aa74f8SRafael Auler "syscall\n" 79*62aa74f8SRafael Auler : "=a"(ret) 80*62aa74f8SRafael Auler : "D"(fd) 81*62aa74f8SRafael Auler : "cc", "rcx", "r11", "memory"); 82*62aa74f8SRafael Auler return ret; 83*62aa74f8SRafael Auler } 84*62aa74f8SRafael Auler 85*62aa74f8SRafael Auler static char *intToStr(char *OutBuf, uint32_t Num, uint32_t Base) { 86*62aa74f8SRafael Auler const char *Chars = "0123456789abcdef"; 87*62aa74f8SRafael Auler char Buf[20]; 88*62aa74f8SRafael Auler char *Ptr = Buf; 89*62aa74f8SRafael Auler while (Num) { 90*62aa74f8SRafael Auler *Ptr++ = *(Chars + (Num % Base)); 91*62aa74f8SRafael Auler Num /= Base; 92*62aa74f8SRafael Auler } 93*62aa74f8SRafael Auler if (Ptr == Buf) { 94*62aa74f8SRafael Auler *OutBuf++ = '0'; 95*62aa74f8SRafael Auler return OutBuf; 96*62aa74f8SRafael Auler } 97*62aa74f8SRafael Auler while (Ptr != Buf) { 98*62aa74f8SRafael Auler *OutBuf++ = *--Ptr; 99*62aa74f8SRafael Auler } 100*62aa74f8SRafael Auler return OutBuf; 101*62aa74f8SRafael Auler } 102*62aa74f8SRafael Auler 103*62aa74f8SRafael Auler static char *serializeLoc(char *OutBuf, uint32_t FuncStrIndex, 104*62aa74f8SRafael Auler uint32_t Offset) { 105*62aa74f8SRafael Auler *OutBuf++ = '1'; 106*62aa74f8SRafael Auler *OutBuf++ = ' '; 107*62aa74f8SRafael Auler char *Str = __bolt_instr_strings + FuncStrIndex; 108*62aa74f8SRafael Auler while (*Str) { 109*62aa74f8SRafael Auler *OutBuf++ = *Str++; 110*62aa74f8SRafael Auler } 111*62aa74f8SRafael Auler *OutBuf++ = ' '; 112*62aa74f8SRafael Auler OutBuf = intToStr(OutBuf, Offset, 16); 113*62aa74f8SRafael Auler *OutBuf++ = ' '; 114*62aa74f8SRafael Auler return OutBuf; 115*62aa74f8SRafael Auler } 116*62aa74f8SRafael Auler 117*62aa74f8SRafael Auler extern "C" void __bolt_instr_data_dump() { 118*62aa74f8SRafael Auler uint64_t FD = myopen(__bolt_instr_filename, 119*62aa74f8SRafael Auler /*flags=*/0x241 /*O_WRONLY|O_TRUNC|O_CREAT*/, 120*62aa74f8SRafael Auler /*mode=*/0666); 121*62aa74f8SRafael Auler 122*62aa74f8SRafael Auler for (int I = 0, E = __bolt_instr_num_locs; I < E; ++I) { 123*62aa74f8SRafael Auler char LineBuf[2000]; 124*62aa74f8SRafael Auler char *Ptr = LineBuf; 125*62aa74f8SRafael Auler uint32_t HitCount = __bolt_instr_locations[I]; 126*62aa74f8SRafael Auler if (!HitCount) 127*62aa74f8SRafael Auler continue; 128*62aa74f8SRafael Auler 129*62aa74f8SRafael Auler EdgeDescription *Desc = &__bolt_instr_descriptions[I]; 130*62aa74f8SRafael Auler Ptr = serializeLoc(Ptr, Desc->From.FunctionName, Desc->From.Offset); 131*62aa74f8SRafael Auler Ptr = serializeLoc(Ptr, Desc->To.FunctionName, Desc->To.Offset); 132*62aa74f8SRafael Auler *Ptr++ = '0'; 133*62aa74f8SRafael Auler *Ptr++ = ' '; 134*62aa74f8SRafael Auler Ptr = intToStr(Ptr, HitCount, 10); 135*62aa74f8SRafael Auler *Ptr++ = '\n'; 136*62aa74f8SRafael Auler mywrite(FD, LineBuf, Ptr - LineBuf); 137*62aa74f8SRafael Auler } 138*62aa74f8SRafael Auler myclose(FD); 139*62aa74f8SRafael Auler } 140