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 20struct 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 33DisassembledCode::DisassembledCode(SourceLanguage* language) 34 : 35 fLanguage(language), 36 fLines(20, true) 37{ 38 fLanguage->AcquireReference(); 39} 40 41 42DisassembledCode::~DisassembledCode() 43{ 44 for (int32 i = 0; Statement* statement = fStatements.ItemAt(i); i++) 45 statement->ReleaseReference(); 46 47 fLanguage->ReleaseReference(); 48} 49 50 51bool 52DisassembledCode::Lock() 53{ 54 // We're immutable, so no locking required. 55 return true; 56} 57 58 59void 60DisassembledCode::Unlock() 61{ 62} 63 64 65SourceLanguage* 66DisassembledCode::GetSourceLanguage() const 67{ 68 return fLanguage; 69} 70 71 72int32 73DisassembledCode::CountLines() const 74{ 75 return fLines.CountItems(); 76} 77 78 79const char* 80DisassembledCode::LineAt(int32 index) const 81{ 82 Line* line = fLines.ItemAt(index); 83 return line != NULL ? line->line.String() : NULL; 84} 85 86 87int32 88DisassembledCode::LineLengthAt(int32 index) const 89{ 90 Line* line = fLines.ItemAt(index); 91 return line != NULL ? line->line.Length() : 0; 92} 93 94 95bool 96DisassembledCode::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 110LocatableFile* 111DisassembledCode::GetSourceFile() const 112{ 113 return NULL; 114} 115 116 117Statement* 118DisassembledCode::StatementAtLocation(const SourceLocation& location) const 119{ 120 Line* line = fLines.ItemAt(location.Line()); 121 return line != NULL ? line->statement : NULL; 122} 123 124 125Statement* 126DisassembledCode::StatementAtAddress(target_addr_t address) const 127{ 128 return fStatements.BinarySearchByKey(address, &_CompareAddressStatement); 129} 130 131 132TargetAddressRange 133DisassembledCode::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 146bool 147DisassembledCode::AddCommentLine(const BString& line) 148{ 149 return _AddLine(line, NULL); 150} 151 152 153bool 154DisassembledCode::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 176bool 177DisassembledCode::_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 193DisassembledCode::_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