|
24 | 24 | #include <inttypes.h> |
25 | 25 | #include <vector> |
26 | 26 | #include "binaryninjaapi.h" |
| 27 | +#include "lowlevelilinstruction.h" |
27 | 28 | #include "ffi.h" |
28 | 29 |
|
29 | 30 | using namespace BinaryNinja; |
@@ -203,6 +204,235 @@ vector<InstructionTextToken> InstructionTextToken::ConvertInstructionTextTokenLi |
203 | 204 | return result; |
204 | 205 | } |
205 | 206 |
|
| 207 | +BasicBlockAnalysisContext::BasicBlockAnalysisContext(BNBasicBlockAnalysisContext* context) |
| 208 | +{ |
| 209 | + m_context = context; |
| 210 | +} |
| 211 | + |
| 212 | +const std::map<ArchAndAddr, std::set<ArchAndAddr>> BasicBlockAnalysisContext::GetIndirectBranches() |
| 213 | +{ |
| 214 | + if (!m_indirectBranches) |
| 215 | + { |
| 216 | + auto& indirectBranches = m_indirectBranches.emplace(); |
| 217 | + |
| 218 | + for (size_t i = 0; i < m_context->indirectBranchesCount; i++) |
| 219 | + { |
| 220 | + ArchAndAddr src(new CoreArchitecture(m_context->indirectBranches[i].sourceArch), m_context->indirectBranches[i].sourceAddr); |
| 221 | + ArchAndAddr dst(new CoreArchitecture(m_context->indirectBranches[i].destArch), m_context->indirectBranches[i].destAddr); |
| 222 | + |
| 223 | + indirectBranches[src].insert(dst); |
| 224 | + } |
| 225 | + } |
| 226 | + |
| 227 | + return *m_indirectBranches; |
| 228 | +} |
| 229 | + |
| 230 | + |
| 231 | +const std::set<ArchAndAddr>& BasicBlockAnalysisContext::GetIndirectNoReturnCalls() |
| 232 | +{ |
| 233 | + if (!m_indirectNoReturnCalls) |
| 234 | + { |
| 235 | + auto& indirectNoReturnCalls = m_indirectNoReturnCalls.emplace(); |
| 236 | + |
| 237 | + for (size_t i = 0; i < m_context->indirectNoReturnCallsCount; i++) |
| 238 | + { |
| 239 | + ArchAndAddr addr(new CoreArchitecture(m_context->indirectNoReturnCalls[i].arch), m_context->indirectNoReturnCalls[i].address); |
| 240 | + indirectNoReturnCalls.insert(addr); |
| 241 | + } |
| 242 | + } |
| 243 | + |
| 244 | + return *m_indirectNoReturnCalls; |
| 245 | +} |
| 246 | + |
| 247 | + |
| 248 | +std::map<ArchAndAddr, bool>& BasicBlockAnalysisContext::GetContextualReturns() |
| 249 | +{ |
| 250 | + if (!m_contextualReturns) |
| 251 | + { |
| 252 | + auto& contextualReturns = m_contextualReturns.emplace(); |
| 253 | + |
| 254 | + for (size_t i = 0; i < m_context->contextualFunctionReturnCount; i++) |
| 255 | + { |
| 256 | + ArchAndAddr addr(new CoreArchitecture(m_context->contextualFunctionReturnLocations[i].arch), m_context->contextualFunctionReturnLocations[i].address); |
| 257 | + contextualReturns[addr] = m_context->contextualFunctionReturnValues[i]; |
| 258 | + } |
| 259 | + } |
| 260 | + |
| 261 | + return *m_contextualReturns; |
| 262 | +} |
| 263 | + |
| 264 | + |
| 265 | +std::map<uint64_t, std::set<ArchAndAddr>>& BasicBlockAnalysisContext::GetDirectCodeReferences() |
| 266 | +{ |
| 267 | + if (!m_directCodeReferences) |
| 268 | + { |
| 269 | + auto& directCodeReferences = m_directCodeReferences.emplace(); |
| 270 | + |
| 271 | + for (size_t i = 0; i < m_context->directRefCount; i++) |
| 272 | + { |
| 273 | + ArchAndAddr src(new CoreArchitecture(m_context->directRefSources[i].arch), m_context->directRefSources[i].address); |
| 274 | + |
| 275 | + directCodeReferences[m_context->directRefTargets[i]].insert(src); |
| 276 | + } |
| 277 | + } |
| 278 | + |
| 279 | + return *m_directCodeReferences; |
| 280 | +} |
| 281 | + |
| 282 | + |
| 283 | +std::set<ArchAndAddr>& BasicBlockAnalysisContext::GetDirectNoReturnCalls() |
| 284 | +{ |
| 285 | + if (!m_directNoReturnCalls) |
| 286 | + m_directNoReturnCalls.emplace(); |
| 287 | + |
| 288 | + return *m_directNoReturnCalls; |
| 289 | +} |
| 290 | + |
| 291 | + |
| 292 | +std::set<ArchAndAddr>& BasicBlockAnalysisContext::GetHaltedDisassemblyAddresses() |
| 293 | +{ |
| 294 | + if (!m_haltedDisassemblyAddresses) |
| 295 | + m_haltedDisassemblyAddresses.emplace(); |
| 296 | + |
| 297 | + return *m_haltedDisassemblyAddresses; |
| 298 | +} |
| 299 | + |
| 300 | + |
| 301 | +void BasicBlockAnalysisContext::AddTempOutgoingReference(Function* targetFunc) |
| 302 | +{ |
| 303 | + BNAnalyzeBasicBlocksContextAddTempReference(m_context, targetFunc->m_object); |
| 304 | +} |
| 305 | + |
| 306 | + |
| 307 | +Ref<BasicBlock> BasicBlockAnalysisContext::CreateBasicBlock(Architecture* arch, uint64_t start) |
| 308 | +{ |
| 309 | + BNBasicBlock* block = BNAnalyzeBasicBlocksContextCreateBasicBlock(m_context, arch->GetObject(), start); |
| 310 | + if (!block) |
| 311 | + return nullptr; |
| 312 | + return new BasicBlock(block); |
| 313 | +} |
| 314 | + |
| 315 | + |
| 316 | +void BasicBlockAnalysisContext::AddFunctionBasicBlock(BasicBlock* block) |
| 317 | +{ |
| 318 | + BNAnalyzeBasicBlocksContextAddBasicBlockToFunction(m_context, block->GetObject()); |
| 319 | +} |
| 320 | + |
| 321 | + |
| 322 | +void BasicBlockAnalysisContext::Finalize() |
| 323 | +{ |
| 324 | + if (m_directCodeReferences) |
| 325 | + { |
| 326 | + auto& directRefs = *m_directCodeReferences; |
| 327 | + |
| 328 | + size_t total = 0; |
| 329 | + for (auto& pair : directRefs) |
| 330 | + total += pair.second.size(); |
| 331 | + |
| 332 | + BNArchitectureAndAddress* sources = new BNArchitectureAndAddress[total]; |
| 333 | + uint64_t* targets = new uint64_t[total]; |
| 334 | + |
| 335 | + size_t i = 0; |
| 336 | + for (auto& pair : directRefs) |
| 337 | + { |
| 338 | + for (auto& src : pair.second) |
| 339 | + { |
| 340 | + sources[i].arch = src.arch->GetObject(); |
| 341 | + sources[i].address = src.address; |
| 342 | + targets[i] = pair.first; |
| 343 | + i++; |
| 344 | + } |
| 345 | + } |
| 346 | + |
| 347 | + BNAnalyzeBasicBlocksContextSetDirectCodeReferences(m_context, sources, targets, total); |
| 348 | + |
| 349 | + delete[] sources; |
| 350 | + delete[] targets; |
| 351 | + } |
| 352 | + |
| 353 | + if (m_directNoReturnCalls) |
| 354 | + { |
| 355 | + auto& directNoReturnCalls = *m_directNoReturnCalls; |
| 356 | + |
| 357 | + BNArchitectureAndAddress* noRets = new BNArchitectureAndAddress[directNoReturnCalls.size()]; |
| 358 | + |
| 359 | + size_t i = 0; |
| 360 | + for (auto& addr : directNoReturnCalls) |
| 361 | + { |
| 362 | + noRets[i].arch = addr.arch->GetObject(); |
| 363 | + noRets[i].address = addr.address; |
| 364 | + i++; |
| 365 | + } |
| 366 | + |
| 367 | + BNAnalyzeBasicBlocksContextSetDirectNoReturnCalls(m_context, noRets, directNoReturnCalls.size()); |
| 368 | + delete[] noRets; |
| 369 | + } |
| 370 | + |
| 371 | + if (m_haltedDisassemblyAddresses) |
| 372 | + { |
| 373 | + auto& haltedDisassemblyAddresses = *m_haltedDisassemblyAddresses; |
| 374 | + |
| 375 | + BNArchitectureAndAddress* haltedAddresses = new BNArchitectureAndAddress[haltedDisassemblyAddresses.size()]; |
| 376 | + |
| 377 | + size_t i = 0; |
| 378 | + for (auto& addr : haltedDisassemblyAddresses) |
| 379 | + { |
| 380 | + haltedAddresses[i].arch = addr.arch->GetObject(); |
| 381 | + haltedAddresses[i].address = addr.address; |
| 382 | + i++; |
| 383 | + } |
| 384 | + |
| 385 | + BNAnalyzeBasicBlocksContextSetHaltedDisassemblyAddresses(m_context, haltedAddresses, haltedDisassemblyAddresses.size()); |
| 386 | + delete[] haltedAddresses; |
| 387 | + } |
| 388 | + |
| 389 | + if (m_contextualReturns) |
| 390 | + { |
| 391 | + auto& contextualReturns = *m_contextualReturns; |
| 392 | + |
| 393 | + bool dirty = contextualReturns.size() != m_context->contextualFunctionReturnCount; |
| 394 | + |
| 395 | + if (!dirty) |
| 396 | + { |
| 397 | + size_t i = 0; |
| 398 | + for (auto& pair : contextualReturns) |
| 399 | + { |
| 400 | + if (pair.first.arch->GetObject() != m_context->contextualFunctionReturnLocations[i].arch |
| 401 | + || pair.first.address != m_context->contextualFunctionReturnLocations[i].address |
| 402 | + || pair.second != m_context->contextualFunctionReturnValues[i]) |
| 403 | + { |
| 404 | + dirty = true; |
| 405 | + break; |
| 406 | + } |
| 407 | + |
| 408 | + i++; |
| 409 | + } |
| 410 | + } |
| 411 | + |
| 412 | + if (dirty) |
| 413 | + { |
| 414 | + BNArchitectureAndAddress* returns = new BNArchitectureAndAddress[contextualReturns.size()]; |
| 415 | + bool* values = new bool[contextualReturns.size()]; |
| 416 | + |
| 417 | + size_t i = 0; |
| 418 | + for (auto& pair : contextualReturns) |
| 419 | + { |
| 420 | + returns[i].arch = pair.first.arch->GetObject(); |
| 421 | + returns[i].address = pair.first.address; |
| 422 | + values[i] = pair.second; |
| 423 | + i++; |
| 424 | + } |
| 425 | + |
| 426 | + BNAnalyzeBasicBlocksContextSetContextualFunctionReturns(m_context, returns, values, contextualReturns.size()); |
| 427 | + |
| 428 | + delete[] returns; |
| 429 | + delete[] values; |
| 430 | + } |
| 431 | + } |
| 432 | + |
| 433 | + BNAnalyzeBasicBlocksContextFinalize(m_context); |
| 434 | +} |
| 435 | + |
206 | 436 |
|
207 | 437 | Architecture::Architecture(BNArchitecture* arch) |
208 | 438 | { |
@@ -327,6 +557,17 @@ bool Architecture::GetInstructionLowLevelILCallback( |
327 | 557 | } |
328 | 558 |
|
329 | 559 |
|
| 560 | +void Architecture::AnalyzeBasicBlocksCallback(void *ctxt, BNFunction* function, |
| 561 | + BNBasicBlockAnalysisContext* context) |
| 562 | +{ |
| 563 | + CallbackRef<Architecture> arch(ctxt); |
| 564 | + BasicBlockAnalysisContext abbc(context); |
| 565 | + Ref<Function> func(new Function(BNNewFunctionReference(function))); |
| 566 | + |
| 567 | + arch->AnalyzeBasicBlocks(func, abbc); |
| 568 | +} |
| 569 | + |
| 570 | + |
330 | 571 | char* Architecture::GetRegisterNameCallback(void* ctxt, uint32_t reg) |
331 | 572 | { |
332 | 573 | CallbackRef<Architecture> arch(ctxt); |
@@ -817,6 +1058,7 @@ void Architecture::Register(Architecture* arch) |
817 | 1058 | callbacks.getInstructionText = GetInstructionTextCallback; |
818 | 1059 | callbacks.freeInstructionText = FreeInstructionTextCallback; |
819 | 1060 | callbacks.getInstructionLowLevelIL = GetInstructionLowLevelILCallback; |
| 1061 | + callbacks.analyzeBasicBlocks = AnalyzeBasicBlocksCallback; |
820 | 1062 | callbacks.getRegisterName = GetRegisterNameCallback; |
821 | 1063 | callbacks.getFlagName = GetFlagNameCallback; |
822 | 1064 | callbacks.getFlagWriteTypeName = GetFlagWriteTypeNameCallback; |
@@ -945,6 +1187,12 @@ bool Architecture::GetInstructionLowLevelIL(const uint8_t*, uint64_t, size_t&, L |
945 | 1187 | } |
946 | 1188 |
|
947 | 1189 |
|
| 1190 | +void Architecture::AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context) |
| 1191 | +{ |
| 1192 | + DefaultAnalyzeBasicBlocks(function, context); |
| 1193 | +} |
| 1194 | + |
| 1195 | + |
948 | 1196 | string Architecture::GetRegisterName(uint32_t reg) |
949 | 1197 | { |
950 | 1198 | return fmt::format("r{}", reg); |
@@ -1505,6 +1753,12 @@ bool CoreArchitecture::GetInstructionLowLevelIL(const uint8_t* data, uint64_t ad |
1505 | 1753 | } |
1506 | 1754 |
|
1507 | 1755 |
|
| 1756 | +void CoreArchitecture::AnalyzeBasicBlocks(Function* function, BasicBlockAnalysisContext& context) |
| 1757 | +{ |
| 1758 | + BNArchitectureAnalyzeBasicBlocks(m_object, function->GetObject(), context.m_context); |
| 1759 | +} |
| 1760 | + |
| 1761 | + |
1508 | 1762 | string CoreArchitecture::GetRegisterName(uint32_t reg) |
1509 | 1763 | { |
1510 | 1764 | char* name = BNGetArchitectureRegisterName(m_object, reg); |
|
0 commit comments