The Pedigree Project  0.1
instrument.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "instrument.h"
21 
22 #define USE_LITE_RECORD 1
23 
24 extern "C" {
25 void __cyg_profile_func_enter(void *func_address, void *call_site)
26  __attribute__((no_instrument_function)) __attribute__((hot));
27 
28 #define COM1 0x3F8
29 #define COM2 0x2F8
30 #define COM3 0x3E8
31 #define COM4 0x2E8
32 
33 #ifdef INSTRUMENTATION
34 static volatile int g_WrittenFirst = 0;
35 #endif
36 
37 void __cyg_profile_func_enter(void *func_address, void *call_site)
38 {
39 #ifdef INSTRUMENTATION
40 // NOTE: you cannot call anything in this function, as doing so would
41 // re-enter. That means hand-crafted serial writes are necessary.
42 #ifdef X64
43  if (UNLIKELY(g_WrittenFirst == 0))
44  {
45  if (__sync_bool_compare_and_swap(&g_WrittenFirst, 0, 1))
46  {
47  uint8_t flag = 0;
48 #if USE_LITE_RECORD
49  flag |= INSTRUMENT_GLOBAL_LITE;
50 #endif
51  asm volatile("outb %%al, %%dx" ::"d"(COM2), "a"(flag));
52  }
53  }
54 
55 #if USE_LITE_RECORD
57 #else
58  InstrumentationRecord record;
59  record.data.flags = INSTRUMENT_RECORD_ENTRY;
60  record.data.caller = reinterpret_cast<uintptr_t>(call_site);
61  record.data.magic = INSTRUMENT_MAGIC;
62 #endif
63  record.data.function = reinterpret_cast<uintptr_t>(func_address);
64 
65  // Semi-unrolled, all-in-one assembly serial-port write.
66  uintptr_t x = 0;
67  size_t y = 0;
68  asm volatile("pushf; cli;"
69  ".1:\n"
70  "movq (%0), %%rax;"
71  "outb %%al, %%dx;"
72  "shr $8, %%rax;"
73  "outb %%al, %%dx;"
74  "shr $8, %%rax;"
75  "outb %%al, %%dx;"
76  "shr $8, %%rax;"
77  "outb %%al, %%dx;"
78  "add $4, %0;"
79  "sub $4, %1;"
80  "jnz .1; popf"
81  : "=&r"(x), "=&r"(y)
82  : "d"(COM2), "0"(record.buffer), "1"(sizeof record.buffer)
83  : "rax", "memory");
84 #endif
85 #endif
86 }
87 
88 } // extern "C"