1/*
2 * Copyright 2015, Rene Gollent, rene@gollent.com.
3 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8#include "AddressValueNode.h"
9
10#include <new>
11
12#include "AddressValue.h"
13#include "Architecture.h"
14#include "Tracing.h"
15#include "Type.h"
16#include "ValueLoader.h"
17#include "ValueLocation.h"
18#include "ValueNodeContainer.h"
19
20
21// #pragma mark - AddressValueNode
22
23
24AddressValueNode::AddressValueNode(ValueNodeChild* nodeChild,
25	AddressType* type)
26	:
27	ValueNode(nodeChild),
28	fType(type),
29	fChild(NULL)
30{
31	fType->AcquireReference();
32}
33
34
35AddressValueNode::~AddressValueNode()
36{
37	if (fChild != NULL)
38		fChild->ReleaseReference();
39	fType->ReleaseReference();
40}
41
42
43Type*
44AddressValueNode::GetType() const
45{
46	return fType;
47}
48
49
50status_t
51AddressValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
52	ValueLocation*& _location, Value*& _value)
53{
54	// get the location
55	ValueLocation* location = NodeChild()->Location();
56	if (location == NULL)
57		return B_BAD_VALUE;
58
59	TRACE_LOCALS("  TYPE_ADDRESS\n");
60
61	// get the value type
62	type_code valueType;
63	if (valueLoader->GetArchitecture()->AddressSize() == 4) {
64		valueType = B_UINT32_TYPE;
65		TRACE_LOCALS("    -> 32 bit\n");
66	} else {
67		valueType = B_UINT64_TYPE;
68		TRACE_LOCALS("    -> 64 bit\n");
69	}
70
71	// load the value data
72	BVariant valueData;
73	status_t error = valueLoader->LoadValue(location, valueType, false,
74		valueData);
75	if (error != B_OK)
76		return error;
77
78	// create the type object
79	Value* value = new(std::nothrow) AddressValue(valueData);
80	if (value == NULL)
81		return B_NO_MEMORY;
82
83	location->AcquireReference();
84	_location = location;
85	_value = value;
86	return B_OK;
87}
88
89
90status_t
91AddressValueNode::CreateChildren(TeamTypeInformation* info)
92{
93	if (fChild != NULL)
94		return B_OK;
95
96	// For function pointers, don't bother creating a child, as there
97	// currently isn't any useful information that can be presented there,
98	// and the address node's value already indicates the instruction pointer
99	// of the target function.
100	// TODO: an eventual future possibility might be for a child node to
101	// indicate the name of the function being pointed to, if target address
102	// is valid.
103	Type* baseType = fType->BaseType();
104	if (baseType != NULL && baseType->Kind() == TYPE_FUNCTION)
105		return B_OK;
106
107	// construct name
108	BString name = "*";
109	name << Name();
110
111	// create the child
112	fChild = new(std::nothrow) AddressValueNodeChild(this, name,
113		baseType);
114	if (fChild == NULL)
115		return B_NO_MEMORY;
116
117	fChild->SetContainer(fContainer);
118
119	if (fContainer != NULL)
120		fContainer->NotifyValueNodeChildrenCreated(this);
121
122	return B_OK;
123}
124
125
126int32
127AddressValueNode::CountChildren() const
128{
129	return fChild != NULL ? 1 : 0;
130}
131
132
133ValueNodeChild*
134AddressValueNode::ChildAt(int32 index) const
135{
136	return index == 0 ? fChild : NULL;
137}
138
139
140// #pragma mark - AddressValueNodeChild
141
142
143AddressValueNodeChild::AddressValueNodeChild(AddressValueNode* parent,
144	const BString& name, Type* type)
145	:
146	fParent(parent),
147	fName(name),
148	fType(type)
149{
150	fType->AcquireReference();
151}
152
153
154AddressValueNodeChild::~AddressValueNodeChild()
155{
156	fType->ReleaseReference();
157}
158
159
160const BString&
161AddressValueNodeChild::Name() const
162{
163	return fName;
164}
165
166
167Type*
168AddressValueNodeChild::GetType() const
169{
170	return fType;
171}
172
173
174ValueNode*
175AddressValueNodeChild::Parent() const
176{
177	return fParent;
178}
179
180
181status_t
182AddressValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
183	ValueLocation*& _location)
184{
185	// The parent's value is an address pointing to this component.
186	AddressValue* parentValue = dynamic_cast<AddressValue*>(
187		fParent->GetValue());
188	if (parentValue == NULL)
189		return B_BAD_VALUE;
190
191	// resolve the location
192	ValueLocation* location;
193	status_t error = fType->ResolveObjectDataLocation(parentValue->ToUInt64(),
194		location);
195	if (error != B_OK) {
196		TRACE_LOCALS("AddressValueNodeChild::ResolveLocation(): "
197			"ResolveObjectDataLocation() failed: %s\n", strerror(error));
198		return error;
199	}
200
201	_location = location;
202	return B_OK;
203}
204