1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2014-2017, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
5 */
6
7#include "DwarfManager.h"
8
9#include <new>
10
11#include <AutoDeleter.h>
12#include <AutoLocker.h>
13
14#include "DwarfFile.h"
15#include "DwarfFileLoadingState.h"
16
17
18DwarfManager::DwarfManager(uint8 addressSize, bool isBigEndian)
19	:
20	fAddressSize(addressSize), fIsBigEndian(isBigEndian),
21	fLock("dwarf manager")
22{
23}
24
25
26DwarfManager::~DwarfManager()
27{
28	while (DwarfFile* file = fFiles.RemoveHead())
29		file->ReleaseReference();
30}
31
32
33status_t
34DwarfManager::Init()
35{
36	return fLock.InitCheck();
37}
38
39
40status_t
41DwarfManager::LoadFile(const char* fileName, DwarfFileLoadingState& _state)
42{
43	AutoLocker<DwarfManager> locker(this);
44
45	DwarfFile* file = _state.dwarfFile;
46	BReference<DwarfFile> fileReference;
47	if (file == NULL) {
48		file = new(std::nothrow) DwarfFile;
49		if (file == NULL)
50			return B_NO_MEMORY;
51		fileReference.SetTo(file, true);
52		_state.dwarfFile = file;
53	} else
54		fileReference.SetTo(file);
55
56	status_t error;
57	if (_state.externalInfoFileName.IsEmpty()) {
58		error = file->StartLoading(fileName, _state.externalInfoFileName);
59		if (error != B_OK) {
60			// only preserve state in the failure case if an external
61			// debug information reference was found, but the corresponding
62			// file could not be located on disk.
63			_state.state = _state.externalInfoFileName.IsEmpty()
64				? DWARF_FILE_LOADING_STATE_FAILED
65				: DWARF_FILE_LOADING_STATE_USER_INPUT_NEEDED;
66
67			return error;
68		}
69	}
70
71	error = file->Load(fAddressSize, fIsBigEndian, _state.locatedExternalInfoPath);
72	if (error != B_OK) {
73		_state.state = DWARF_FILE_LOADING_STATE_FAILED;
74		return error;
75	}
76
77	fFiles.Add(file);
78
79	fileReference.Detach();
80		// keep a reference for ourselves in the list.
81
82	_state.state = DWARF_FILE_LOADING_STATE_SUCCEEDED;
83
84	return B_OK;
85}
86
87
88status_t
89DwarfManager::FinishLoading()
90{
91	AutoLocker<DwarfManager> locker(this);
92
93	for (FileList::Iterator it = fFiles.GetIterator();
94			DwarfFile* file = it.Next();) {
95		status_t error = file->FinishLoading(fAddressSize, fIsBigEndian);
96		if (error != B_OK)
97			return error;
98	}
99
100	return B_OK;
101}
102