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
LineDisassembledCode::Line24 Line(const BString& line, ContiguousStatement* statement)
25 :
26 line(line),
27 statement(statement)
28 {
29 }
30 };
31
32
DisassembledCode(SourceLanguage * language)33 DisassembledCode::DisassembledCode(SourceLanguage* language)
34 :
35 fLanguage(language),
36 fLines(20, true)
37 {
38 fLanguage->AcquireReference();
39 }
40
41
~DisassembledCode()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
Lock()52 DisassembledCode::Lock()
53 {
54 // We're immutable, so no locking required.
55 return true;
56 }
57
58
59 void
Unlock()60 DisassembledCode::Unlock()
61 {
62 }
63
64
65 SourceLanguage*
GetSourceLanguage() const66 DisassembledCode::GetSourceLanguage() const
67 {
68 return fLanguage;
69 }
70
71
72 int32
CountLines() const73 DisassembledCode::CountLines() const
74 {
75 return fLines.CountItems();
76 }
77
78
79 const char*
LineAt(int32 index) const80 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
LineLengthAt(int32 index) const88 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
GetStatementLocationRange(const SourceLocation & location,SourceLocation & _start,SourceLocation & _end) const96 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*
GetSourceFile() const111 DisassembledCode::GetSourceFile() const
112 {
113 return NULL;
114 }
115
116
117 Statement*
StatementAtLocation(const SourceLocation & location) const118 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*
StatementAtAddress(target_addr_t address) const126 DisassembledCode::StatementAtAddress(target_addr_t address) const
127 {
128 return fStatements.BinarySearchByKey(address, &_CompareAddressStatement);
129 }
130
131
132 TargetAddressRange
StatementAddressRange() const133 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
AddCommentLine(const BString & line)147 DisassembledCode::AddCommentLine(const BString& line)
148 {
149 return _AddLine(line, NULL);
150 }
151
152
153 bool
AddInstructionLine(const BString & line,target_addr_t address,target_size_t size)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
_AddLine(const BString & _line,ContiguousStatement * statement)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
_CompareAddressStatement(const target_addr_t * address,const ContiguousStatement * statement)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