~ubuntu-branches/ubuntu/maverick/clamav/maverick-backports

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Stephen Gran, Stephen Gran, Michael Tautschnig
  • Date: 2010-04-26 21:41:18 UTC
  • mfrom: (2.1.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100426214118-i6lo606wnh7ywfj6
Tags: 0.96+dfsg-4
[ Stephen Gran ]
* Fixed typo in clamav-milter's postinst

[ Michael Tautschnig ]
* Fixed typo in clamav-freshclam's postinst (closes: #579271)
* Debconf translation updates
  - Portuguese (closes: #579068)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is distributed under the University of Illinois Open Source
 
6
// License. See LICENSE.TXT for details.
 
7
//
 
8
//===----------------------------------------------------------------------===//
 
9
//
 
10
// This file defines a JITEventListener object that calls into OProfile to tell
 
11
// it about JITted functions.  For now, we only record function names and sizes,
 
12
// but eventually we'll also record line number information.
 
13
//
 
14
// See http://oprofile.sourceforge.net/doc/devel/jit-interface.html for the
 
15
// definition of the interface we're using.
 
16
//
 
17
//===----------------------------------------------------------------------===//
 
18
 
 
19
#define DEBUG_TYPE "oprofile-jit-event-listener"
 
20
#include "llvm/Function.h"
 
21
#include "llvm/Metadata.h"
 
22
#include "llvm/Analysis/DebugInfo.h"
 
23
#include "llvm/CodeGen/MachineFunction.h"
 
24
#include "llvm/ExecutionEngine/JITEventListener.h"
 
25
#include "llvm/Support/Debug.h"
 
26
#include "llvm/Support/ValueHandle.h"
 
27
#include "llvm/Support/raw_ostream.h"
 
28
#include "llvm/System/Errno.h"
 
29
#include "llvm/Config/config.h"
 
30
#include <stddef.h>
 
31
using namespace llvm;
 
32
 
 
33
#if USE_OPROFILE
 
34
 
 
35
#include <opagent.h>
 
36
 
 
37
namespace {
 
38
 
 
39
class OProfileJITEventListener : public JITEventListener {
 
40
  op_agent_t Agent;
 
41
public:
 
42
  OProfileJITEventListener();
 
43
  ~OProfileJITEventListener();
 
44
 
 
45
  virtual void NotifyFunctionEmitted(const Function &F,
 
46
                                     void *FnStart, size_t FnSize,
 
47
                                     const EmittedFunctionDetails &Details);
 
48
  virtual void NotifyFreeingMachineCode(void *OldPtr);
 
49
};
 
50
 
 
51
OProfileJITEventListener::OProfileJITEventListener()
 
52
    : Agent(op_open_agent()) {
 
53
  if (Agent == NULL) {
 
54
    const std::string err_str = sys::StrError();
 
55
    DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n");
 
56
  } else {
 
57
    DEBUG(dbgs() << "Connected to OProfile agent.\n");
 
58
  }
 
59
}
 
60
 
 
61
OProfileJITEventListener::~OProfileJITEventListener() {
 
62
  if (Agent != NULL) {
 
63
    if (op_close_agent(Agent) == -1) {
 
64
      const std::string err_str = sys::StrError();
 
65
      DEBUG(dbgs() << "Failed to disconnect from OProfile agent: "
 
66
                   << err_str << "\n");
 
67
    } else {
 
68
      DEBUG(dbgs() << "Disconnected from OProfile agent.\n");
 
69
    }
 
70
  }
 
71
}
 
72
 
 
73
class FilenameCache {
 
74
  // Holds the filename of each Scope, so that we can pass a null-terminated
 
75
  // string into oprofile.  Use an AssertingVH rather than a ValueMap because we
 
76
  // shouldn't be modifying any MDNodes while this map is alive.
 
77
  DenseMap<AssertingVH<MDNode>, std::string> Filenames;
 
78
 
 
79
 public:
 
80
  const char *getFilename(DIScope Scope) {
 
81
    std::string &Filename = Filenames[Scope.getNode()];
 
82
    if (Filename.empty()) {
 
83
      Filename = Scope.getFilename();
 
84
    }
 
85
    return Filename.c_str();
 
86
  }
 
87
};
 
88
 
 
89
static debug_line_info LineStartToOProfileFormat(
 
90
    const MachineFunction &MF, FilenameCache &Filenames,
 
91
    uintptr_t Address, DebugLoc Loc) {
 
92
  debug_line_info Result;
 
93
  Result.vma = Address;
 
94
  DILocation DILoc = MF.getDILocation(Loc);
 
95
  Result.lineno = DILoc.getLineNumber();
 
96
  Result.filename = Filenames.getFilename(DILoc.getScope());
 
97
  DEBUG(dbgs() << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to "
 
98
               << Result.filename << ":" << Result.lineno << "\n");
 
99
  return Result;
 
100
}
 
101
 
 
102
// Adds the just-emitted function to the symbol table.
 
103
void OProfileJITEventListener::NotifyFunctionEmitted(
 
104
    const Function &F, void *FnStart, size_t FnSize,
 
105
    const EmittedFunctionDetails &Details) {
 
106
  assert(F.hasName() && FnStart != 0 && "Bad symbol to add");
 
107
  if (op_write_native_code(Agent, F.getName().data(),
 
108
                           reinterpret_cast<uint64_t>(FnStart),
 
109
                           FnStart, FnSize) == -1) {
 
110
    DEBUG(dbgs() << "Failed to tell OProfile about native function " 
 
111
          << F.getName() << " at [" 
 
112
          << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
 
113
    return;
 
114
  }
 
115
 
 
116
  // Now we convert the line number information from the address/DebugLoc format
 
117
  // in Details to the address/filename/lineno format that OProfile expects.
 
118
  // OProfile 0.9.4 (and maybe later versions) has a bug that causes it to
 
119
  // ignore line numbers for addresses above 4G.
 
120
  FilenameCache Filenames;
 
121
  std::vector<debug_line_info> LineInfo;
 
122
  LineInfo.reserve(1 + Details.LineStarts.size());
 
123
  if (!Details.MF->getDefaultDebugLoc().isUnknown()) {
 
124
    LineInfo.push_back(LineStartToOProfileFormat(
 
125
        *Details.MF, Filenames,
 
126
        reinterpret_cast<uintptr_t>(FnStart),
 
127
        Details.MF->getDefaultDebugLoc()));
 
128
  }
 
129
  for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator
 
130
           I = Details.LineStarts.begin(), E = Details.LineStarts.end();
 
131
       I != E; ++I) {
 
132
    LineInfo.push_back(LineStartToOProfileFormat(
 
133
        *Details.MF, Filenames, I->Address, I->Loc));
 
134
  }
 
135
  if (!LineInfo.empty()) {
 
136
    if (op_write_debug_line_info(Agent, FnStart,
 
137
                                 LineInfo.size(), &*LineInfo.begin()) == -1) {
 
138
      DEBUG(dbgs() 
 
139
            << "Failed to tell OProfile about line numbers for native function "
 
140
            << F.getName() << " at [" 
 
141
            << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
 
142
    }
 
143
  }
 
144
}
 
145
 
 
146
// Removes the being-deleted function from the symbol table.
 
147
void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
 
148
  assert(FnStart && "Invalid function pointer");
 
149
  if (op_unload_native_code(Agent, reinterpret_cast<uint64_t>(FnStart)) == -1) {
 
150
    DEBUG(dbgs()
 
151
          << "Failed to tell OProfile about unload of native function at "
 
152
          << FnStart << "\n");
 
153
  }
 
154
}
 
155
 
 
156
}  // anonymous namespace.
 
157
 
 
158
namespace llvm {
 
159
JITEventListener *createOProfileJITEventListener() {
 
160
  return new OProfileJITEventListener;
 
161
}
 
162
}
 
163
 
 
164
#else  // USE_OPROFILE
 
165
 
 
166
namespace llvm {
 
167
// By defining this to return NULL, we can let clients call it unconditionally,
 
168
// even if they haven't configured with the OProfile libraries.
 
169
JITEventListener *createOProfileJITEventListener() {
 
170
  return NULL;
 
171
}
 
172
}  // namespace llvm
 
173
 
 
174
#endif  // USE_OPROFILE