#include "Symtab.h"
#include "CodeSource.h"
#include "CodeObject.h"
#include "CFG.h"
#include <iostream>
#include <algorithm>

namespace st = Dyninst::SymtabAPI;
namespace pa = Dyninst::ParseAPI;

int main(int argc, char *argv[]){
  if(argc != 2) {
    std::cerr << "Usage: " << argv[0] << " file\n";
    return -1;
  }
  
  auto *symtab_source = new pa::SymtabCodeSource(argv[1]);
  auto *co = new pa::CodeObject(symtab_source);
 
  auto const& funcs = co->funcs();
  auto *first = *funcs.begin();
  auto *last = *funcs.rbegin();
  
  std::cout << "Found " << funcs.size() << " functions in range ["
            << std::hex << first->addr() << ","
            << std::hex << last->addr() << ")\n";
  
  constexpr auto addr = 0x1d77979;
  //constexpr auto addr = 0x1d77480;
  bool found = false;
  for (auto *f : funcs) {
    for(auto b : f->blocks()) {
      if(b->start() > 0x1d7747f && b->end() < 0x1d779a0)
        fprintf(stderr, "block startend %lx,%lx\n", b->start(),b->end());
      if(b->containsAddr(addr)) {
        fprintf(stderr, "found addr1 %lx\n", addr);
        std::cout << f->name()
                  << "   [" << std::hex << b->start() << ", "
                  << std::hex << b->end() << ")\n";
        found = true;
        //break;
      }
      else if(b->containsAddr(0x1d7797e) ){
        fprintf(stderr, "found addr2 %lx\n", addr);
        std::cout << f->name()
                  << "   [" << std::hex << b->start() << ", "
                  << std::hex << b->end() << ")\n";
        found = true;
        break;
      }
      else if(b->containsAddr(0x1d77983) ){
        fprintf(stderr, "found addr3 %lx\n", addr);
        std::cout << f->name()
                  << "   [" << std::hex << b->start() << ", "
                  << std::hex << b->end() << ")\n";
        found = true;
        break;
      }
      else if(b->containsAddr(0x1d779874) ){
        fprintf(stderr, "found addr4 %lx\n", addr);
        std::cout << f->name()
                  << "   [" << std::hex << b->start() << ", "
                  << std::hex << b->end() << ")\n";
        found = true;
        break;
      }
      else if(b->containsAddr(0x1d7798c) ){
        fprintf(stderr, "found addr5 %lx\n", addr);
        std::cout << f->name()
                  << "   [" << std::hex << b->start() << ", "
                  << std::hex << b->end() << ")\n";
        found = true;
        break;
      }
      else if(b->containsAddr(0x1d77991) ){
        fprintf(stderr, "found addr6 %lx\n", addr);
        std::cout << f->name()
                  << "   [" << std::hex << b->start() << ", "
                  << std::hex << b->end() << ")\n";
        found = true;
        break;
      }
      else if(b->containsAddr(0x1d77997) ){
        fprintf(stderr, "found addr7 %lx\n", addr);
        std::cout << f->name()
                  << "   [" << std::hex << b->start() << ", "
                  << std::hex << b->end() << ")\n";
        found = true;
        break;
      }
      else if(b->containsAddr(0x1d77480) ){
        fprintf(stderr, "found addr8 0x1d77480\n");
        std::cout << f->name()
                  << " found  [" << std::hex << b->start() << ", "
                  << std::hex << b->end() << ")\n";
        found = true;
        //break;
      }
    }
  }
  
  if(!found) {
    std::cout << "Found no block for address " << std::hex << addr << '\n';
  }
}