vfs: check userland buffers before reading them.
[haiku.git] / src / kits / debugger / debug_info / TeamDebugInfo.cpp
blob5ed9ba1e88b3027e8788aa1f988bd24e6d97209a
1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2012-2016, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
5 */
8 #include "TeamDebugInfo.h"
10 #include <stdio.h>
12 #include <new>
14 #include <AutoDeleter.h>
15 #include <AutoLocker.h>
17 #include "Architecture.h"
18 #include "DebuggerInterface.h"
19 #include "DebuggerTeamDebugInfo.h"
20 #include "DisassembledCode.h"
21 #include "DwarfTeamDebugInfo.h"
22 #include "FileManager.h"
23 #include "FileSourceCode.h"
24 #include "Function.h"
25 #include "FunctionID.h"
26 #include "ImageDebugInfo.h"
27 #include "ImageDebugInfoLoadingState.h"
28 #include "LocatableFile.h"
29 #include "SourceFile.h"
30 #include "SourceLanguage.h"
31 #include "SpecificImageDebugInfo.h"
32 #include "StringUtils.h"
33 #include "Type.h"
34 #include "TypeLookupConstraints.h"
37 // #pragma mark - FunctionHashDefinition
40 struct TeamDebugInfo::FunctionHashDefinition {
41 typedef const FunctionInstance* KeyType;
42 typedef Function ValueType;
44 size_t HashKey(const FunctionInstance* key) const
46 // Instances without source file only equal themselves.
47 if (key->SourceFile() == NULL)
48 return (uint32)(addr_t)key;
50 uint32 hash = StringUtils::HashValue(key->Name());
51 hash = hash * 17 + (uint32)(addr_t)key->SourceFile();
52 SourceLocation location = key->GetSourceLocation();
53 hash = hash * 17 + location.Line();
54 hash = hash * 17 + location.Column();
56 return hash;
59 size_t Hash(const Function* value) const
61 return HashKey(value->FirstInstance());
64 bool Compare(const FunctionInstance* key, const Function* value) const
66 // source file must be the same
67 if (key->SourceFile() != value->SourceFile())
68 return false;
70 // Instances without source file only equal themselves.
71 if (key->SourceFile() == NULL)
72 return key == value->FirstInstance();
74 // Source location and function name must also match.
75 return key->GetSourceLocation() == value->GetSourceLocation()
76 && key->Name() == value->Name();
79 Function*& GetLink(Function* value) const
81 return value->fNext;
86 // #pragma mark - SourceFileEntry
89 struct TeamDebugInfo::SourceFileEntry {
90 SourceFileEntry(LocatableFile* sourceFile)
92 fSourceFile(sourceFile),
93 fSourceCode(NULL)
95 fSourceFile->AcquireReference();
98 ~SourceFileEntry()
100 SetSourceCode(NULL);
101 fSourceFile->ReleaseReference();
104 status_t Init()
106 return B_OK;
109 LocatableFile* SourceFile() const
111 return fSourceFile;
114 FileSourceCode* GetSourceCode() const
116 return fSourceCode;
119 void SetSourceCode(FileSourceCode* sourceCode)
121 if (sourceCode == fSourceCode)
122 return;
124 if (fSourceCode != NULL)
125 fSourceCode->ReleaseReference();
127 fSourceCode = sourceCode;
129 if (fSourceCode != NULL)
130 fSourceCode->AcquireReference();
134 bool IsUnused() const
136 return fFunctions.IsEmpty();
139 status_t AddFunction(Function* function)
141 if (!fFunctions.BinaryInsert(function, &_CompareFunctions))
142 return B_NO_MEMORY;
144 return B_OK;
147 void RemoveFunction(Function* function)
149 int32 index = fFunctions.BinarySearchIndex(*function,
150 &_CompareFunctions);
151 if (index >= 0)
152 fFunctions.RemoveItemAt(index);
155 Function* FunctionAtLocation(const SourceLocation& location) const
157 int32 index = fFunctions.BinarySearchIndexByKey(location,
158 &_CompareLocationFunction);
159 if (index >= 0)
160 return fFunctions.ItemAt(index);
162 // No exact match, so we return the previous function which might still
163 // contain the location.
164 index = -index - 1;
166 if (index == 0)
167 return NULL;
169 return fFunctions.ItemAt(index - 1);
172 Function* FunctionAt(int32 index) const
174 return fFunctions.ItemAt(index);
177 Function* FunctionByName(const BString& name) const
179 // TODO: That's not exactly optimal.
180 for (int32 i = 0; Function* function = fFunctions.ItemAt(i); i++) {
181 if (name == function->Name())
182 return function;
184 return NULL;
187 private:
188 typedef BObjectList<Function> FunctionList;
190 private:
191 static int _CompareFunctions(const Function* a, const Function* b)
193 SourceLocation locationA = a->GetSourceLocation();
194 SourceLocation locationB = b->GetSourceLocation();
196 if (locationA < locationB)
197 return -1;
199 if (locationA != locationB )
200 return 1;
202 // if the locations match we still need to compare by name to be
203 // certain, since differently typed instantiations of template
204 // functions will have the same source file and location
205 return a->Name().Compare(b->Name());
208 static int _CompareLocationFunction(const SourceLocation* location,
209 const Function* function)
211 SourceLocation functionLocation = function->GetSourceLocation();
213 if (*location < functionLocation)
214 return -1;
216 return *location == functionLocation ? 0 : 1;
219 private:
220 LocatableFile* fSourceFile;
221 FileSourceCode* fSourceCode;
222 FunctionList fFunctions;
224 public:
225 SourceFileEntry* fNext;
229 // #pragma mark - SourceFileHashDefinition
232 struct TeamDebugInfo::SourceFileHashDefinition {
233 typedef const LocatableFile* KeyType;
234 typedef SourceFileEntry ValueType;
236 size_t HashKey(const LocatableFile* key) const
238 return (size_t)(addr_t)key;
241 size_t Hash(const SourceFileEntry* value) const
243 return HashKey(value->SourceFile());
246 bool Compare(const LocatableFile* key, const SourceFileEntry* value) const
248 return key == value->SourceFile();
251 SourceFileEntry*& GetLink(SourceFileEntry* value) const
253 return value->fNext;
258 // #pragma mark - TeamDebugInfo
261 TeamDebugInfo::TeamDebugInfo(DebuggerInterface* debuggerInterface,
262 Architecture* architecture, FileManager* fileManager)
264 fLock("team debug info"),
265 fDebuggerInterface(debuggerInterface),
266 fArchitecture(architecture),
267 fFileManager(fileManager),
268 fSpecificInfos(10, true),
269 fFunctions(NULL),
270 fSourceFiles(NULL),
271 fTypeCache(NULL),
272 fMainFunction(NULL)
274 fDebuggerInterface->AcquireReference();
278 TeamDebugInfo::~TeamDebugInfo()
280 if (fTypeCache != NULL)
281 fTypeCache->ReleaseReference();
283 if (fSourceFiles != NULL) {
284 SourceFileEntry* entry = fSourceFiles->Clear(true);
285 while (entry != NULL) {
286 SourceFileEntry* next = entry->fNext;
287 delete entry;
288 entry = next;
291 delete fSourceFiles;
294 if (fFunctions != NULL) {
295 Function* function = fFunctions->Clear(true);
296 while (function != NULL) {
297 Function* next = function->fNext;
298 function->ReleaseReference();
299 function = next;
302 delete fFunctions;
305 fDebuggerInterface->ReleaseReference();
309 status_t
310 TeamDebugInfo::Init()
312 // check the lock
313 status_t error = fLock.InitCheck();
314 if (error != B_OK)
315 return error;
317 // create function hash table
318 fFunctions = new(std::nothrow) FunctionTable;
319 if (fFunctions == NULL)
320 return B_NO_MEMORY;
322 error = fFunctions->Init();
323 if (error != B_OK)
324 return error;
326 // create source file hash table
327 fSourceFiles = new(std::nothrow) SourceFileTable;
328 if (fSourceFiles == NULL)
329 return B_NO_MEMORY;
331 error = fSourceFiles->Init();
332 if (error != B_OK)
333 return error;
335 // create a type cache
336 fTypeCache = new(std::nothrow) GlobalTypeCache;
337 if (fTypeCache == NULL)
338 return B_NO_MEMORY;
340 error = fTypeCache->Init();
341 if (error != B_OK)
342 return error;
344 // Create specific infos for all types of debug info we support, in
345 // descending order of expressiveness.
347 // DWARF
348 DwarfTeamDebugInfo* dwarfInfo = new(std::nothrow) DwarfTeamDebugInfo(
349 fArchitecture, fDebuggerInterface, fFileManager, this, this,
350 fTypeCache);
351 if (dwarfInfo == NULL || !fSpecificInfos.AddItem(dwarfInfo)) {
352 delete dwarfInfo;
353 return B_NO_MEMORY;
356 error = dwarfInfo->Init();
357 if (error != B_OK)
358 return error;
360 // debugger based info
361 DebuggerTeamDebugInfo* debuggerInfo
362 = new(std::nothrow) DebuggerTeamDebugInfo(fDebuggerInterface,
363 fArchitecture);
364 if (debuggerInfo == NULL || !fSpecificInfos.AddItem(debuggerInfo)) {
365 delete debuggerInfo;
366 return B_NO_MEMORY;
369 error = debuggerInfo->Init();
370 if (error != B_OK)
371 return error;
373 return B_OK;
377 status_t
378 TeamDebugInfo::LookupTypeByName(const BString& name,
379 const TypeLookupConstraints& constraints, Type*& _type)
381 return GetType(fTypeCache, name, constraints, _type);
385 bool
386 TeamDebugInfo::TypeExistsByName(const BString& name,
387 const TypeLookupConstraints& constraints)
389 return HasType(fTypeCache, name, constraints);
393 status_t
394 TeamDebugInfo::GetType(GlobalTypeCache* cache, const BString& name,
395 const TypeLookupConstraints& constraints, Type*& _type)
397 // maybe the type is already cached
398 AutoLocker<GlobalTypeCache> cacheLocker(cache);
400 Type* type = cache->GetType(name, constraints);
401 if (type != NULL) {
402 type->AcquireReference();
403 _type = type;
404 return B_OK;
407 cacheLocker.Unlock();
409 // Clone the image list and get references to the images, so we can iterate
410 // through them without locking.
411 AutoLocker<BLocker> locker(fLock);
413 ImageList images;
414 for (int32 i = 0; ImageDebugInfo* imageDebugInfo = fImages.ItemAt(i); i++) {
415 if (images.AddItem(imageDebugInfo))
416 imageDebugInfo->AcquireReference();
419 locker.Unlock();
421 // get the type
422 status_t error = B_ENTRY_NOT_FOUND;
423 for (int32 i = 0; ImageDebugInfo* imageDebugInfo = images.ItemAt(i); i++) {
424 error = imageDebugInfo->GetType(cache, name, constraints, type);
425 if (error == B_OK) {
426 _type = type;
427 break;
431 // release the references
432 for (int32 i = 0; ImageDebugInfo* imageDebugInfo = images.ItemAt(i); i++)
433 imageDebugInfo->ReleaseReference();
435 return error;
439 bool
440 TeamDebugInfo::HasType(GlobalTypeCache* cache, const BString& name,
441 const TypeLookupConstraints& constraints)
443 // maybe the type is already cached
444 AutoLocker<GlobalTypeCache> cacheLocker(cache);
446 Type* type = cache->GetType(name, constraints);
447 if (type != NULL)
448 return true;
450 cacheLocker.Unlock();
452 // Clone the image list and get references to the images, so we can iterate
453 // through them without locking.
454 AutoLocker<BLocker> locker(fLock);
456 ImageList images;
457 for (int32 i = 0; ImageDebugInfo* imageDebugInfo = fImages.ItemAt(i); i++) {
458 if (images.AddItem(imageDebugInfo))
459 imageDebugInfo->AcquireReference();
462 locker.Unlock();
464 bool found = false;
465 for (int32 i = 0; ImageDebugInfo* imageDebugInfo = images.ItemAt(i); i++) {
466 if (imageDebugInfo->HasType(name, constraints)) {
467 found = true;
468 break;
472 // release the references
473 for (int32 i = 0; ImageDebugInfo* imageDebugInfo = images.ItemAt(i); i++)
474 imageDebugInfo->ReleaseReference();
476 return found;
480 status_t
481 TeamDebugInfo::GetActiveSourceCode(FunctionDebugInfo* info, SourceCode*& _code)
483 AutoLocker<BLocker> locker(fLock);
485 LocatableFile* file = info->SourceFile();
486 if (file != NULL) {
487 Function* function = FunctionAtSourceLocation(file,
488 info->SourceStartLocation());
489 if (function != NULL) {
490 function_source_state state = function->SourceCodeState();
491 if (function->SourceCodeState() == FUNCTION_SOURCE_LOADED) {
492 _code = function->GetSourceCode();
493 _code->AcquireReference();
494 return B_OK;
495 } else if (state == FUNCTION_SOURCE_NOT_LOADED) {
496 // if the function's source state is not loaded, check
497 // if we already know the file anyways. Currently, when
498 // a source code job runs, it does so on behalf of a specific
499 // function, and consequently only sets the loaded source code
500 // on that particular function at that point in time, rather
501 // than all others sharing that same file. Consequently,
502 // set it lazily here.
503 SourceFileEntry* entry = fSourceFiles->Lookup(file);
504 if (entry != NULL) {
505 FileSourceCode* sourceCode = entry->GetSourceCode();
506 if (sourceCode != NULL) {
507 function->SetSourceCode(sourceCode,
508 FUNCTION_SOURCE_LOADED);
509 _code = sourceCode;
510 _code->AcquireReference();
511 return B_OK;
518 for (int32 i = 0; i < fImages.CountItems(); i++) {
519 ImageDebugInfo* imageInfo = fImages.ItemAt(i);
520 FunctionInstance* instance = imageInfo->FunctionAtAddress(
521 info->Address());
522 if (instance != NULL && instance->SourceCodeState()
523 == FUNCTION_SOURCE_LOADED) {
524 _code = instance->GetSourceCode();
525 _code->AcquireReference();
526 return B_OK;
530 return B_ENTRY_NOT_FOUND;
534 status_t
535 TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo,
536 LocatableFile* imageFile, ImageDebugInfoLoadingState& _state,
537 ImageDebugInfo*& _imageDebugInfo)
539 ImageDebugInfo* imageDebugInfo = new(std::nothrow) ImageDebugInfo(
540 imageInfo);
541 if (imageDebugInfo == NULL)
542 return B_NO_MEMORY;
543 BReference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo, true);
545 for (int32 i = 0; SpecificTeamDebugInfo* specificTeamInfo
546 = fSpecificInfos.ItemAt(i); i++) {
547 SpecificImageDebugInfo* specificImageInfo;
548 status_t error = specificTeamInfo->CreateImageDebugInfo(imageInfo,
549 imageFile, _state, specificImageInfo);
550 if (error == B_OK) {
551 if (!imageDebugInfo->AddSpecificInfo(specificImageInfo)) {
552 delete specificImageInfo;
553 return B_NO_MEMORY;
555 } else if (_state.UserInputRequired()) {
556 _state.SetSpecificInfoIndex(i);
557 return error;
558 } else if (error == B_NO_MEMORY)
559 return error;
560 // fail only when out of memory
562 _state.ClearSpecificDebugInfoLoadingState();
563 // if we made it this far, then we're done with current specific
564 // info, and its corresponding state object, if any, is no longer
565 // needed
568 status_t error = imageDebugInfo->FinishInit(fDebuggerInterface);
569 if (error != B_OK)
570 return error;
572 if (fMainFunction == NULL) {
573 FunctionInstance* instance = imageDebugInfo->MainFunction();
574 if (instance != NULL)
575 fMainFunction = instance;
578 _imageDebugInfo = imageDebugInfoReference.Detach();
579 return B_OK;
583 status_t
584 TeamDebugInfo::LoadSourceCode(LocatableFile* file, FileSourceCode*& _sourceCode)
586 AutoLocker<BLocker> locker(fLock);
588 // If we don't know the source file, there's nothing we can do.
589 SourceFileEntry* entry = fSourceFiles->Lookup(file);
590 if (entry == NULL)
591 return B_ENTRY_NOT_FOUND;
593 // the source might already be loaded
594 FileSourceCode* sourceCode = entry->GetSourceCode();
595 if (sourceCode != NULL) {
596 sourceCode->AcquireReference();
597 _sourceCode = sourceCode;
598 return B_OK;
601 // get the source language from some function's image debug info
602 Function* function = entry->FunctionAt(0);
603 if (function == NULL)
604 return B_ENTRY_NOT_FOUND;
606 FunctionDebugInfo* functionDebugInfo
607 = function->FirstInstance()->GetFunctionDebugInfo();
608 SourceLanguage* language;
609 status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
610 ->GetSourceLanguage(functionDebugInfo, language);
611 if (error != B_OK)
612 return error;
613 BReference<SourceLanguage> languageReference(language, true);
615 // no source code yet
616 // locker.Unlock();
617 // TODO: It would be nice to unlock here, but we need to iterate through
618 // the images below. We could clone the list, acquire references, and
619 // unlock. Then we have to compare the list with the then current list when
620 // we're done loading.
622 // load the source file
623 SourceFile* sourceFile;
624 error = fFileManager->LoadSourceFile(file, sourceFile);
625 if (error != B_OK)
626 return error;
628 // create the source code
629 sourceCode = new(std::nothrow) FileSourceCode(file, sourceFile, language);
630 sourceFile->ReleaseReference();
631 if (sourceCode == NULL)
632 return B_NO_MEMORY;
633 BReference<FileSourceCode> sourceCodeReference(sourceCode, true);
635 error = sourceCode->Init();
636 if (error != B_OK)
637 return error;
639 // Iterate through all images that know the source file and ask them to add
640 // information.
641 bool anyInfo = false;
642 for (int32 i = 0; ImageDebugInfo* imageDebugInfo = fImages.ItemAt(i); i++)
643 anyInfo |= imageDebugInfo->AddSourceCodeInfo(file, sourceCode) == B_OK;
645 if (!anyInfo)
646 return B_ENTRY_NOT_FOUND;
648 entry->SetSourceCode(sourceCode);
650 _sourceCode = sourceCodeReference.Detach();
651 return B_OK;
655 void
656 TeamDebugInfo::ClearSourceCode(LocatableFile* sourceFile)
658 AutoLocker<BLocker> locker(fLock);
660 SourceFileEntry* entry = fSourceFiles->Lookup(sourceFile);
661 if (entry != NULL)
662 entry->SetSourceCode(NULL);
666 status_t
667 TeamDebugInfo::DisassembleFunction(FunctionInstance* functionInstance,
668 DisassembledCode*& _sourceCode)
670 // allocate a buffer for the function code
671 static const target_size_t kMaxBufferSize = 64 * 1024;
672 target_size_t bufferSize = std::min(functionInstance->Size(),
673 kMaxBufferSize);
674 void* buffer = malloc(bufferSize);
675 if (buffer == NULL)
676 return B_NO_MEMORY;
677 MemoryDeleter bufferDeleter(buffer);
679 // read the function code
680 FunctionDebugInfo* functionDebugInfo
681 = functionInstance->GetFunctionDebugInfo();
682 ssize_t bytesRead = functionDebugInfo->GetSpecificImageDebugInfo()
683 ->ReadCode(functionInstance->Address(), buffer, bufferSize);
684 if (bytesRead < 0)
685 return bytesRead;
687 return fArchitecture->DisassembleCode(functionDebugInfo, buffer, bytesRead,
688 _sourceCode);
692 status_t
693 TeamDebugInfo::AddImageDebugInfo(ImageDebugInfo* imageDebugInfo)
695 AutoLocker<BLocker> locker(fLock);
696 // We have both locks now, so that for read-only access either lock
697 // suffices.
699 if (!fImages.AddItem(imageDebugInfo))
700 return B_NO_MEMORY;
702 // Match all of the image debug info's functions instances with functions.
703 BObjectList<SourceFileEntry> sourceFileEntries;
704 for (int32 i = 0;
705 FunctionInstance* instance = imageDebugInfo->FunctionAt(i); i++) {
706 // lookup the function or create it, if it doesn't exist yet
707 Function* function = fFunctions->Lookup(instance);
708 if (function != NULL) {
709 // TODO: Also update possible user breakpoints in this function!
710 function->AddInstance(instance);
711 instance->SetFunction(function);
713 // The new image debug info might have additional information about
714 // the source file of the function, so remember the source file
715 // entry.
716 if (LocatableFile* sourceFile = function->SourceFile()) {
717 SourceFileEntry* entry = fSourceFiles->Lookup(sourceFile);
718 if (entry != NULL && entry->GetSourceCode() != NULL)
719 sourceFileEntries.AddItem(entry);
721 } else {
722 function = new(std::nothrow) Function;
723 if (function == NULL) {
724 RemoveImageDebugInfo(imageDebugInfo);
725 return B_NO_MEMORY;
727 function->AddInstance(instance);
728 instance->SetFunction(function);
730 status_t error = _AddFunction(function);
731 // Insert after adding the instance. Otherwise the function
732 // wouldn't be hashable/comparable.
733 if (error != B_OK) {
734 function->RemoveInstance(instance);
735 instance->SetFunction(NULL);
736 RemoveImageDebugInfo(imageDebugInfo);
737 return error;
742 // update the source files the image debug info knows about
743 for (int32 i = 0; SourceFileEntry* entry = sourceFileEntries.ItemAt(i);
744 i++) {
745 FileSourceCode* sourceCode = entry->GetSourceCode();
746 sourceCode->Lock();
747 if (imageDebugInfo->AddSourceCodeInfo(entry->SourceFile(),
748 sourceCode) == B_OK) {
749 // TODO: Notify interesting parties! Iterate through all functions
750 // for this source file?
752 sourceCode->Unlock();
755 return B_OK;
759 void
760 TeamDebugInfo::RemoveImageDebugInfo(ImageDebugInfo* imageDebugInfo)
762 AutoLocker<BLocker> locker(fLock);
763 // We have both locks now, so that for read-only access either lock
764 // suffices.
766 // Remove the functions from all of the image debug info's functions
767 // instances.
768 for (int32 i = 0;
769 FunctionInstance* instance = imageDebugInfo->FunctionAt(i); i++) {
770 if (Function* function = instance->GetFunction()) {
771 // TODO: Also update possible user breakpoints in this function!
772 if (function->FirstInstance() == function->LastInstance()) {
773 // function unused -- remove it
774 // Note, that we have to remove it from the hash before removing
775 // the instance, since otherwise the function cannot be compared
776 // anymore.
777 _RemoveFunction(function);
778 function->ReleaseReference();
779 // The instance still has a reference.
782 function->RemoveInstance(instance);
783 instance->SetFunction(NULL);
784 // If this was the last instance, it will remove the last
785 // reference to the function.
789 // remove cached types from that image
790 fTypeCache->RemoveTypes(imageDebugInfo->GetImageInfo().ImageID());
792 fImages.RemoveItem(imageDebugInfo);
796 ImageDebugInfo*
797 TeamDebugInfo::ImageDebugInfoByName(const char* name) const
799 for (int32 i = 0; ImageDebugInfo* imageDebugInfo = fImages.ItemAt(i); i++) {
800 if (imageDebugInfo->GetImageInfo().Name() == name)
801 return imageDebugInfo;
804 return NULL;
808 Function*
809 TeamDebugInfo::FunctionAtSourceLocation(LocatableFile* file,
810 const SourceLocation& location) const
812 if (SourceFileEntry* entry = fSourceFiles->Lookup(file))
813 return entry->FunctionAtLocation(location);
814 return NULL;
818 Function*
819 TeamDebugInfo::FunctionByID(FunctionID* functionID) const
821 if (SourceFunctionID* sourceFunctionID
822 = dynamic_cast<SourceFunctionID*>(functionID)) {
823 // get the source file
824 LocatableFile* file = fFileManager->GetSourceFile(
825 sourceFunctionID->SourceFilePath());
826 if (file == NULL)
827 return NULL;
828 BReference<LocatableFile> fileReference(file, true);
830 if (SourceFileEntry* entry = fSourceFiles->Lookup(file))
831 return entry->FunctionByName(functionID->FunctionName());
832 return NULL;
835 ImageFunctionID* imageFunctionID
836 = dynamic_cast<ImageFunctionID*>(functionID);
837 if (imageFunctionID == NULL)
838 return NULL;
840 ImageDebugInfo* imageDebugInfo
841 = ImageDebugInfoByName(imageFunctionID->ImageName());
842 if (imageDebugInfo == NULL)
843 return NULL;
845 FunctionInstance* functionInstance = imageDebugInfo->FunctionByName(
846 functionID->FunctionName());
847 return functionInstance != NULL ? functionInstance->GetFunction() : NULL;
851 status_t
852 TeamDebugInfo::_AddFunction(Function* function)
854 // If the function refers to a source file, add it to the respective entry.
855 if (LocatableFile* sourceFile = function->SourceFile()) {
856 SourceFileEntry* entry = fSourceFiles->Lookup(sourceFile);
857 if (entry == NULL) {
858 // no entry for the source file yet -- create on
859 entry = new(std::nothrow) SourceFileEntry(sourceFile);
860 if (entry == NULL)
861 return B_NO_MEMORY;
863 status_t error = entry->Init();
864 if (error != B_OK) {
865 delete entry;
866 return error;
869 fSourceFiles->Insert(entry);
872 // add the function
873 status_t error = entry->AddFunction(function);
874 if (error != B_OK) {
875 if (entry->IsUnused()) {
876 fSourceFiles->Remove(entry);
877 delete entry;
879 return error;
883 fFunctions->Insert(function);
885 return B_OK;
889 void
890 TeamDebugInfo::_RemoveFunction(Function* function)
892 fFunctions->Remove(function);
894 // If the function refers to a source file, remove it from the respective
895 // entry.
896 if (LocatableFile* sourceFile = function->SourceFile()) {
897 if (SourceFileEntry* entry = fSourceFiles->Lookup(sourceFile))
898 entry->RemoveFunction(function);