2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
7 #include "CallgrindProfileResult.h"
16 #include "ProfiledEntity.h"
19 // #pragma mark - CallgrindImageProfileResult
22 CallgrindImageProfileResult::CallgrindImageProfileResult(SharedImage
* image
,
25 ImageProfileResult(image
, id
),
32 CallgrindImageProfileResult::~CallgrindImageProfileResult()
34 int32 symbolCount
= fImage
->SymbolCount();
35 for (int32 i
= 0; i
< symbolCount
; i
++) {
36 while (CallgrindCalledFunction
* calledFunction
37 = fFunctions
[i
].calledFunctions
) {
38 fFunctions
[i
].calledFunctions
= calledFunction
->next
;
39 delete calledFunction
;
48 CallgrindImageProfileResult::Init()
50 int32 symbolCount
= fImage
->SymbolCount();
51 fFunctions
= new(std::nothrow
) CallgrindFunction
[symbolCount
];
52 if (fFunctions
== NULL
)
55 memset(fFunctions
, 0, sizeof(CallgrindFunction
) * symbolCount
);
62 CallgrindImageProfileResult::AddSymbolHit(int32 symbolIndex
,
63 CallgrindImageProfileResult
* calledImage
, int32 calledSymbol
)
68 CallgrindFunction
& function
= fFunctions
[symbolIndex
];
69 if (calledImage
!= NULL
) {
70 // check whether the called function is known already
71 CallgrindCalledFunction
* calledFunction
= function
.calledFunctions
;
72 while (calledFunction
!= NULL
) {
73 if (calledFunction
->image
== calledImage
74 && calledFunction
->function
== calledSymbol
) {
77 calledFunction
= calledFunction
->next
;
80 // create a new CallgrindCalledFunction object, if not known
81 if (calledFunction
== NULL
) {
82 calledFunction
= new(std::nothrow
) CallgrindCalledFunction(
83 calledImage
, calledSymbol
);
84 if (calledFunction
== NULL
)
87 calledFunction
->next
= function
.calledFunctions
;
88 function
.calledFunctions
= calledFunction
;
91 calledFunction
->hits
++;
98 CallgrindImageProfileResult::Functions() const
105 CallgrindImageProfileResult::OutputIndex() const
112 CallgrindImageProfileResult::SetOutputIndex(int32 index
)
114 fOutputIndex
= index
;
118 // #pragma mark - CallgrindProfileResult
121 CallgrindProfileResult::CallgrindProfileResult()
126 fNextImageOutputIndex(1),
127 fNextFunctionOutputIndex(1)
133 CallgrindProfileResult::AddSamples(ImageProfileResultContainer
* container
,
134 addr_t
* samples
, int32 sampleCount
)
136 int32 unknownSamples
= 0;
137 CallgrindImageProfileResult
* previousImage
= NULL
;
138 int32 previousSymbol
= -1;
140 // TODO: That probably doesn't work with recursive functions.
141 for (int32 i
= 0; i
< sampleCount
; i
++) {
142 addr_t address
= samples
[i
];
144 CallgrindImageProfileResult
* image
145 = static_cast<CallgrindImageProfileResult
*>(
146 container
->FindImage(address
, loadDelta
));
149 symbol
= image
->GetImage()->FindSymbol(address
- loadDelta
);
151 image
->AddSymbolHit(symbol
, previousImage
, previousSymbol
);
152 previousImage
= image
;
153 previousSymbol
= symbol
;
159 if (unknownSamples
== sampleCount
)
167 CallgrindProfileResult::AddDroppedTicks(int32 dropped
)
169 fDroppedTicks
+= dropped
;
174 CallgrindProfileResult::PrintResults(ImageProfileResultContainer
* container
)
176 // create output file
179 mkdir(gOptions
.callgrind_directory
, S_IRWXU
| S_IRWXG
| S_IROTH
| S_IXOTH
);
181 // get the entity name and replace slashes by hyphens
182 char entityName
[B_OS_NAME_LENGTH
];
183 strlcpy(entityName
, fEntity
->EntityName(), sizeof(entityName
));
184 char* slash
= entityName
;
185 while ((slash
= strchr(slash
, '/')) != NULL
)
188 // create the file name
189 char fileName
[B_PATH_NAME_LENGTH
];
190 snprintf(fileName
, sizeof(fileName
), "%s/callgrind.out.%ld.%s.%lldms",
191 gOptions
.callgrind_directory
, fEntity
->EntityID(), entityName
,
192 fTotalTicks
* fInterval
);
195 FILE* out
= fopen(fileName
, "w+");
197 fprintf(stderr
, "%s: Failed to open output file \"%s\": %s\n",
198 kCommandName
, fileName
, strerror(errno
));
203 fprintf(out
, "version: 1\n");
204 fprintf(out
, "creator: Haiku profile\n");
205 fprintf(out
, "pid: %ld\n", fEntity
->EntityID());
206 fprintf(out
, "cmd: %s\n", fEntity
->EntityName());
207 fprintf(out
, "part: 1\n\n");
209 fprintf(out
, "positions: line\n");
210 fprintf(out
, "events: Ticks Time\n");
211 fprintf(out
, "summary: %lld %lld\n", fTotalTicks
, fTotalTicks
* fInterval
);
214 CallgrindImageProfileResult
* images
[container
->CountImages()];
215 int32 imageCount
= GetHitImages(container
, images
);
217 for (int32 i
= 0; i
< imageCount
; i
++) {
218 CallgrindImageProfileResult
* image
= images
[i
];
220 CallgrindFunction
* functions
= image
->Functions();
221 int32 imageSymbolCount
= image
->GetImage()->SymbolCount();
222 for (int32 k
= 0; k
< imageSymbolCount
; k
++) {
223 CallgrindFunction
& function
= functions
[k
];
224 if (function
.hits
== 0 && function
.calledFunctions
== NULL
)
228 _PrintFunction(out
, image
, k
, false);
229 fprintf(out
, "0 %lld %lld\n", function
.hits
,
230 function
.hits
* fInterval
);
232 CallgrindCalledFunction
* calledFunction
= function
.calledFunctions
;
233 while (calledFunction
!= NULL
) {
234 _PrintFunction(out
, calledFunction
->image
,
235 calledFunction
->function
, true);
236 fprintf(out
, "calls=%lld 0\n", calledFunction
->hits
);
237 fprintf(out
, "0 %lld %lld\n", calledFunction
->hits
,
238 calledFunction
->hits
* fInterval
);
239 calledFunction
= calledFunction
->next
;
244 // print pseudo-functions for unknown and dropped ticks
245 if (fUnkownTicks
+ fDroppedTicks
> 0) {
246 fprintf(out
, "\nob=<pseudo>\n");
248 if (fUnkownTicks
> 0) {
249 fprintf(out
, "\nfn=unknown\n");
250 fprintf(out
, "0 %lld\n", fUnkownTicks
);
253 if (fDroppedTicks
> 0) {
254 fprintf(out
, "\nfn=dropped\n");
255 fprintf(out
, "0 %lld\n", fDroppedTicks
);
259 fprintf(out
, "\ntotals: %lld %lld\n", fTotalTicks
, fTotalTicks
* fInterval
);
266 CallgrindProfileResult::GetImageProfileResult(SharedImage
* image
, image_id id
,
267 ImageProfileResult
*& _imageResult
)
269 CallgrindImageProfileResult
* result
270 = new(std::nothrow
) CallgrindImageProfileResult(image
, id
);
274 status_t error
= result
->Init();
280 _imageResult
= result
;
286 CallgrindProfileResult::_PrintFunction(FILE* out
,
287 CallgrindImageProfileResult
* image
, int32 functionIndex
, bool called
)
289 if (image
->OutputIndex() == 0) {
290 // need to print the image name
291 int32 index
= fNextImageOutputIndex
++;
292 image
->SetOutputIndex(index
);
293 fprintf(out
, "%sob=(%ld) %s:%ld\n", called
? "c" : "", index
,
294 image
->GetImage()->Name(), image
->ID());
296 // image is already known
297 // TODO: We may not need to print it at all!
298 fprintf(out
, "%sob=(%ld)\n", called
? "c" : "", image
->OutputIndex());
301 CallgrindFunction
& function
= image
->Functions()[functionIndex
];
302 if (function
.outputIndex
== 0) {
303 // need to print the function name
304 function
.outputIndex
= fNextFunctionOutputIndex
++;
305 fprintf(out
, "%sfn=(%ld) %s\n", called
? "c" : "", function
.outputIndex
,
306 image
->GetImage()->Symbols()[functionIndex
]->Name());
308 // function is already known
309 fprintf(out
, "%sfn=(%ld)\n", called
? "c" : "", function
.outputIndex
);