xref: /haiku/src/kits/debugger/model/DisassembledCode.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "DisassembledCode.h"
8 
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include <new>
13 
14 #include <String.h>
15 
16 #include "SourceLanguage.h"
17 #include "Statement.h"
18 
19 
20 struct DisassembledCode::Line {
21 	BString					line;
22 	ContiguousStatement*	statement;
23 
24 	Line(const BString& line, ContiguousStatement* statement)
25 		:
26 		line(line),
27 		statement(statement)
28 	{
29 	}
30 };
31 
32 
33 DisassembledCode::DisassembledCode(SourceLanguage* language)
34 	:
35 	fLanguage(language),
36 	fLines(20, true)
37 {
38 	fLanguage->AcquireReference();
39 }
40 
41 
42 DisassembledCode::~DisassembledCode()
43 {
44 	for (int32 i = 0; Statement* statement = fStatements.ItemAt(i); i++)
45 		statement->ReleaseReference();
46 
47 	fLanguage->ReleaseReference();
48 }
49 
50 
51 bool
52 DisassembledCode::Lock()
53 {
54 	// We're immutable, so no locking required.
55 	return true;
56 }
57 
58 
59 void
60 DisassembledCode::Unlock()
61 {
62 }
63 
64 
65 SourceLanguage*
66 DisassembledCode::GetSourceLanguage() const
67 {
68 	return fLanguage;
69 }
70 
71 
72 int32
73 DisassembledCode::CountLines() const
74 {
75 	return fLines.CountItems();
76 }
77 
78 
79 const char*
80 DisassembledCode::LineAt(int32 index) const
81 {
82 	Line* line = fLines.ItemAt(index);
83 	return line != NULL ? line->line.String() : NULL;
84 }
85 
86 
87 int32
88 DisassembledCode::LineLengthAt(int32 index) const
89 {
90 	Line* line = fLines.ItemAt(index);
91 	return line != NULL ? line->line.Length() : 0;
92 }
93 
94 
95 bool
96 DisassembledCode::GetStatementLocationRange(const SourceLocation& location,
97 	SourceLocation& _start, SourceLocation& _end) const
98 {
99 	Line* line = fLines.ItemAt(location.Line());
100 	if (line == NULL || line->statement == NULL)
101 		return false;
102 
103 	_start = line->statement->StartSourceLocation();
104 	_end = SourceLocation(_start.Line() + 1);
105 		// TODO: Multi-line instructions!
106 	return true;
107 }
108 
109 
110 LocatableFile*
111 DisassembledCode::GetSourceFile() const
112 {
113 	return NULL;
114 }
115 
116 
117 Statement*
118 DisassembledCode::StatementAtLocation(const SourceLocation& location) const
119 {
120 	Line* line = fLines.ItemAt(location.Line());
121 	return line != NULL ? line->statement : NULL;
122 }
123 
124 
125 Statement*
126 DisassembledCode::StatementAtAddress(target_addr_t address) const
127 {
128 	return fStatements.BinarySearchByKey(address, &_CompareAddressStatement);
129 }
130 
131 
132 TargetAddressRange
133 DisassembledCode::StatementAddressRange() const
134 {
135 	if (fStatements.IsEmpty())
136 		return TargetAddressRange();
137 
138 	ContiguousStatement* first = fStatements.ItemAt(0);
139 	ContiguousStatement* last
140 		= fStatements.ItemAt(fStatements.CountItems() - 1);
141 	return TargetAddressRange(first->AddressRange().Start(),
142 		last->AddressRange().End());
143 }
144 
145 
146 bool
147 DisassembledCode::AddCommentLine(const BString& line)
148 {
149 	return _AddLine(line, NULL);
150 }
151 
152 
153 bool
154 DisassembledCode::AddInstructionLine(const BString& line, target_addr_t address,
155 	target_size_t size)
156 {
157 	int32 lineIndex = fLines.CountItems();
158 
159 	ContiguousStatement* statement = new(std::nothrow) ContiguousStatement(
160 		SourceLocation(lineIndex), TargetAddressRange(address, size));
161 	if (statement == NULL)
162 		return false;
163 
164 	if (!fStatements.AddItem(statement)) {
165 		delete statement;
166 		return false;
167 	}
168 
169 	if (!_AddLine(line, statement))
170 		return false;
171 
172 	return true;
173 }
174 
175 
176 bool
177 DisassembledCode::_AddLine(const BString& _line, ContiguousStatement* statement)
178 {
179 	Line* line = new(std::nothrow) Line(_line, statement);
180 	if (line == NULL)
181 		return false;
182 
183 	if (!fLines.AddItem(line)) {
184 		delete line;
185 		return false;
186 	}
187 
188 	return true;
189 }
190 
191 
192 /*static*/ int
193 DisassembledCode::_CompareAddressStatement(const target_addr_t* address,
194 	const ContiguousStatement* statement)
195 {
196 	const TargetAddressRange& range = statement->AddressRange();
197 
198 	if (*address < range.Start())
199 		return -1;
200 	return *address < range.End() ? 0 : 1;
201 }
202 
203