| 149 | } |
| 150 | |
| 151 | void FunctionBrowserWidget::LoadFromModules() { |
| 152 | functions.clear(); |
| 153 | |
| 154 | auto* process = system.ApplicationProcess(); |
| 155 | if (!process) { |
| 156 | table->setRowCount(0); |
| 157 | return; |
| 158 | } |
| 159 | |
| 160 | auto modules = Core::FindModules(process); |
| 161 | auto& memory = process->GetMemory(); |
| 162 | bool is_64 = process->Is64Bit(); |
| 163 | |
| 164 | for (const auto& [base_addr, module_name] : modules) { |
| 165 | auto symbols = Core::Symbols::GetSymbols(base_addr, memory, is_64); |
| 166 | for (const auto& [sym_name, addr_size] : symbols) { |
| 167 | u64 addr = base_addr + addr_size.first; // base_addr + offset = absolute address |
| 168 | u64 size = addr_size.second; |
| 169 | |
| 170 | std::string name = sym_name; |
| 171 | auto it = ghidra_import_overrides.find(addr); |
| 172 | if (it != ghidra_import_overrides.end()) { |
| 173 | name = it->second; |
| 174 | } |
| 175 | |
| 176 | functions.push_back({addr, name, size, module_name}); |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | // Add any Ghidra imports that weren't in symbols (e.g. manually named) |
| 181 | for (const auto& [addr, name] : ghidra_import_overrides) { |
| 182 | bool found = false; |
| 183 | for (const auto& f : functions) { |
| 184 | if (f.address == addr) { |
| 185 | found = true; |
| 186 | break; |
| 187 | } |
| 188 | } |
| 189 | if (!found) { |
| 190 | functions.push_back({addr, name, 0, "(imported)"}); |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | // Sort by address |
| 195 | std::sort(functions.begin(), functions.end(), |
| 196 | [](const FunctionEntry& a, const FunctionEntry& b) { return a.address < b.address; }); |
| 197 | |
| 198 | OnFilterTextChanged(filter_input->text()); |
| 199 | } |
| 200 | |
| 201 | void FunctionBrowserWidget::OnFilterTextChanged(const QString& text) { |
| 202 | QString q = text.trimmed().toLower(); |
nothing calls this directly
no test coverage detected