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