vfs: check userland buffers before reading them.
[haiku.git] / src / bin / debug / profile / BasicProfileResult.cpp
blob52f707fbd2dfc0cf9369fd7291cb24de85a621c3
1 /*
2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "BasicProfileResult.h"
9 #if __GNUC__ > 2
10 #include <cxxabi.h>
11 #endif
12 #include <stdio.h>
14 #include <algorithm>
15 #include <new>
17 #include "Options.h"
18 #include "ProfiledEntity.h"
21 struct HitSymbol {
22 int64 hits;
23 Symbol* symbol;
24 image_id imageID;
26 inline bool operator<(const HitSymbol& other) const
28 return hits > other.hits;
33 // #pragma mark - BasicImageProfileResult
36 BasicImageProfileResult::BasicImageProfileResult(SharedImage* image,
37 image_id id)
39 ImageProfileResult(image, id),
40 fSymbolHits(NULL),
41 fUnknownHits(0)
46 BasicImageProfileResult::~BasicImageProfileResult()
51 status_t
52 BasicImageProfileResult::Init()
54 int32 symbolCount = fImage->SymbolCount();
55 fSymbolHits = new(std::nothrow) int64[symbolCount];
56 if (fSymbolHits == NULL)
57 return B_NO_MEMORY;
59 memset(fSymbolHits, 0, 8 * symbolCount);
61 return B_OK;
65 bool
66 BasicImageProfileResult::AddHit(addr_t address)
68 int32 symbolIndex = fImage->FindSymbol(address);
69 if (symbolIndex < 0)
70 return false;
72 fSymbolHits[symbolIndex]++;
73 fTotalHits++;
75 return true;
79 void
80 BasicImageProfileResult::AddUnknownHit()
82 fUnknownHits++;
83 fTotalHits++;
87 void
88 BasicImageProfileResult::AddSymbolHit(int32 symbolIndex)
90 fSymbolHits[symbolIndex]++;
94 void
95 BasicImageProfileResult::AddImageHit()
97 fTotalHits++;
101 const int64*
102 BasicImageProfileResult::SymbolHits() const
104 return fSymbolHits;
108 int64
109 BasicImageProfileResult::UnknownHits() const
111 return fUnknownHits;
115 // #pragma mark - BasicProfileResult
118 BasicProfileResult::BasicProfileResult()
120 fTotalTicks(0),
121 fUnkownTicks(0),
122 fDroppedTicks(0),
123 fTotalSampleCount(0)
128 void
129 BasicProfileResult::AddDroppedTicks(int32 dropped)
131 fDroppedTicks += dropped;
135 void
136 BasicProfileResult::PrintResults(ImageProfileResultContainer* container)
138 // get hit images
139 BasicImageProfileResult* images[container->CountImages()];
140 int32 imageCount = GetHitImages(container, images);
142 // count symbols
143 int32 symbolCount = 0;
144 for (int32 k = 0; k < imageCount; k++) {
145 BasicImageProfileResult* image = images[k];
146 if (image->TotalHits() > image->UnknownHits())
147 symbolCount += image->GetImage()->SymbolCount();
150 // find and sort the hit symbols
151 HitSymbol hitSymbols[symbolCount];
152 int32 hitSymbolCount = 0;
154 for (int32 k = 0; k < imageCount; k++) {
155 BasicImageProfileResult* image = images[k];
156 if (image->TotalHits() > image->UnknownHits()) {
157 Symbol** symbols = image->GetImage()->Symbols();
158 const int64* symbolHits = image->SymbolHits();
159 int32 imageSymbolCount = image->GetImage()->SymbolCount();
160 for (int32 i = 0; i < imageSymbolCount; i++) {
161 if (symbolHits[i] > 0) {
162 HitSymbol& hitSymbol = hitSymbols[hitSymbolCount++];
163 hitSymbol.hits = symbolHits[i];
164 hitSymbol.symbol = symbols[i];
165 hitSymbol.imageID = image->ID();
171 if (hitSymbolCount > 1)
172 std::sort(hitSymbols, hitSymbols + hitSymbolCount);
174 int64 totalTicks = fTotalTicks;
175 fprintf(gOptions.output, "\nprofiling results for %s \"%s\" "
176 "(%" B_PRId32 "):\n", fEntity->EntityType(), fEntity->EntityName(),
177 fEntity->EntityID());
178 fprintf(gOptions.output, " tick interval: %lld us\n", fInterval);
179 fprintf(gOptions.output, " total ticks: %lld (%lld us)\n",
180 totalTicks, totalTicks * fInterval);
181 if (totalTicks == 0)
182 totalTicks = 1;
183 fprintf(gOptions.output, " unknown ticks: %lld (%lld us, %6.2f%%)\n",
184 fUnkownTicks, fUnkownTicks * fInterval,
185 100.0 * fUnkownTicks / totalTicks);
186 fprintf(gOptions.output, " dropped ticks: %lld (%lld us, %6.2f%%)\n",
187 fDroppedTicks, fDroppedTicks * fInterval,
188 100.0 * fDroppedTicks / totalTicks);
189 if (gOptions.analyze_full_stack) {
190 fprintf(gOptions.output, " samples/tick: %.1f\n",
191 (double)fTotalSampleCount / totalTicks);
194 if (imageCount > 0) {
195 fprintf(gOptions.output, "\n");
196 fprintf(gOptions.output, " hits unknown image\n");
197 fprintf(gOptions.output, " ---------------------------------------"
198 "---------------------------------------\n");
199 for (int32 k = 0; k < imageCount; k++) {
200 BasicImageProfileResult* image = images[k];
201 fprintf(gOptions.output, " %10lld %10lld %7ld %s\n",
202 image->TotalHits(), image->UnknownHits(),
203 image->ID(), image->GetImage()->Name());
207 if (hitSymbolCount > 0) {
208 fprintf(gOptions.output, "\n");
209 fprintf(gOptions.output, " hits in us in %% "
210 "image function\n");
211 fprintf(gOptions.output, " ---------------------------------------"
212 "---------------------------------------\n");
213 for (int32 i = 0; i < hitSymbolCount; i++) {
214 const HitSymbol& hitSymbol = hitSymbols[i];
215 const Symbol* symbol = hitSymbol.symbol;
216 #if __GNUC__ > 2
217 int status;
218 const char* symbolName = __cxxabiv1::__cxa_demangle(symbol->Name(),
219 NULL, NULL, &status);
220 if (symbolName == NULL)
221 symbolName = symbol->Name();
222 #else
223 const char* symbolName = symbol->Name();
224 #endif
225 fprintf(gOptions.output, " %10lld %10lld %6.2f %6ld %s\n",
226 hitSymbol.hits, hitSymbol.hits * fInterval,
227 100.0 * hitSymbol.hits / totalTicks, hitSymbol.imageID,
228 symbolName);
229 #if __GNUC__ > 2
230 if (status == 0)
231 free(const_cast<char*>(symbolName));
232 #endif
234 } else
235 fprintf(gOptions.output, " no functions were hit\n");
239 status_t
240 BasicProfileResult::GetImageProfileResult(SharedImage* image, image_id id,
241 ImageProfileResult*& _imageResult)
243 BasicImageProfileResult* result
244 = new(std::nothrow) BasicImageProfileResult(image, id);
245 if (result == NULL)
246 return B_NO_MEMORY;
248 status_t error = result->Init();
249 if (error != B_OK) {
250 delete result;
251 return error;
254 _imageResult = result;
255 return B_OK;
259 // #pragma mark - InclusiveProfileResult
262 void
263 InclusiveProfileResult::AddSamples(ImageProfileResultContainer* container,
264 addr_t* samples, int32 sampleCount)
266 // Sort the samples. This way hits of the same symbol are
267 // successive and we can avoid incrementing the hit count of the
268 // same symbol twice. Same for images.
269 std::sort(samples, samples + sampleCount);
271 int32 unknownSamples = 0;
272 BasicImageProfileResult* previousImage = NULL;
273 int32 previousSymbol = -1;
275 for (int32 i = 0; i < sampleCount; i++) {
276 addr_t address = samples[i];
277 addr_t loadDelta;
278 BasicImageProfileResult* image = static_cast<BasicImageProfileResult*>(
279 container->FindImage(address, loadDelta));
280 int32 symbol = -1;
281 if (image != NULL) {
282 symbol = image->GetImage()->FindSymbol(address - loadDelta);
283 if (symbol < 0) {
284 // TODO: Count unknown image hits?
285 } else if (image != previousImage || symbol != previousSymbol)
286 image->AddSymbolHit(symbol);
288 if (image != previousImage)
289 image->AddImageHit();
290 } else
291 unknownSamples++;
293 previousImage = image;
294 previousSymbol = symbol;
297 if (unknownSamples == sampleCount)
298 fUnkownTicks++;
300 fTotalTicks++;
301 fTotalSampleCount += sampleCount;
305 // #pragma mark - ExclusiveProfileResult
308 void
309 ExclusiveProfileResult::AddSamples(ImageProfileResultContainer* container,
310 addr_t* samples, int32 sampleCount)
312 BasicImageProfileResult* image = NULL;
313 // the image in which we hit a symbol
314 BasicImageProfileResult* firstImage = NULL;
315 // the first image we hit, != image if no symbol was hit
317 for (int32 k = 0; k < sampleCount; k++) {
318 addr_t address = samples[k];
319 addr_t loadDelta;
320 image = static_cast<BasicImageProfileResult*>(
321 container->FindImage(address, loadDelta));
322 if (image != NULL) {
323 if (image->AddHit(address - loadDelta))
324 break;
325 if (firstImage == NULL)
326 firstImage = image;
330 if (image == NULL) {
331 if (firstImage != NULL)
332 firstImage->AddUnknownHit();
333 else
334 fUnkownTicks++;
337 fTotalTicks++;
338 fTotalSampleCount += sampleCount;