stevehopwoodforex.com
https://www.stevehopwoodforex.com/phpBB3/
Print view

How do you debug a Empty4 DLL?
https://www.stevehopwoodforex.com/phpBB3/viewtopic.php?t=1709
Page 1 of 1
Author:  jcl [ Fri Mar 29, 2013 8:50 am ]
Post subject:  How do you debug a Empty4 DLL?

I recently had to debug a C++ DLL for an Empty4 EA, but Empty4 crashes whenever I attach the VC++ debugger to the terminal.exe process. This seems to be due to some crude mechanism in Empty4 to prevent reverse engineering.

Has someone else run into the same problem? Is there a safe method to debug DLL functions called from an EA, or do I have to write some Empty4 simulator for that purpose?
Author:  stratman [ Tue Apr 02, 2013 8:27 pm ]
Post subject:  Re: How do you debug a Empty4 DLL?

The last build of Empty4 that could be debugged was 225.

Empty4 has debug protection built in provided by 'themida'.

As a DLL developer I have the same issues. I program using a lot of unit testing by debugging directly in my IDE. This does mean that I have to simulate a lot of the trading platform functions.

I load bars and ticks from text files. I also include pre-calculated indicator values for each bar. Here's the code (no cpp as all code is in this header). I'll do a second post to show how I unit test:

Code: Select all

#ifndef PIPWARE_DATA_HELPER_HPP_
#define PIPWARE_DATA_HELPER_HPP_

#include<iostream>
#include<fstream>
#include<iterator>
#include<string>
#include<vector>
#include<queue>

namespace pipware
{

  struct TestTick {
    long        time;
    std::string timestamp;
    double      bid;
    double      ask;
    double      bidVol;
    double      askVol;
  };

  struct TestBar {
      long        time;
      std::string timestamp;
      double      open;
      double      high;
      double      low;
      double      close;
      double      volume;
      double      maTotal;
      double      ma;
      double      stochMin;
      double      stochMax;
      double      stochK;
      double      stochSlope;
      int         fractalLow;
      int         fractalHigh;
  };

  std::vector<TestBar> H1TestBars;
  std::vector<TestBar> M15TestBars;
  std::vector<TestBar> M5TestBars;
  std::vector<TestBar> M1TestBars;
  std::vector<TestTick> TestTicks;

  std::vector<TestBar> ReadTestBars( std::string filePath )
  {
    std::cout << "Reading: " << filePath << " ... " << std::flush;
    std::ifstream file(filePath.c_str());
    std::vector<TestBar> bars((std::istream_iterator<TestBar>(file)), std::istream_iterator<TestBar>());
    file.close();
    std::cout << "Done" << std::endl;
    return (bars);
  }

  std::vector<TestTick> ReadTestTicks( std::string filePath )
  {
    std::cout << "Reading: " << filePath << " ... " << std::flush;
    std::ifstream file(filePath.c_str());
    std::vector<TestTick> ticks((std::istream_iterator<TestTick>(file)), std::istream_iterator<TestTick>());
    file.close();
    std::cout << "Done" << std::endl;
    return (ticks);
  }

  template<class Ch, class Tr>
  std::basic_istream<Ch,Tr>& operator>>(std::basic_istream<Ch,Tr>& in, TestTick& t)
  {
      return in
          >> t.time
          >> t.timestamp
          >> t.bid
          >> t.ask
          >> t.bidVol
          >> t.askVol
          ;
  }

  template<class Ch, class Tr>
  std::basic_istream<Ch,Tr>& operator>>(std::basic_istream<Ch,Tr>& in, TestBar& b)
  {
      return in
          >> b.time
          >> b.timestamp
          >> b.open
          >> b.high
          >> b.low
          >> b.close
          >> b.volume
          >> b.maTotal
          >> b.ma
          >> b.stochMin
          >> b.stochMax
          >> b.stochK
          >> b.stochSlope
          >> b.fractalLow
          >> b.fractalHigh
          ;
  }

  void InitDataFromFiles(std::string dir)
  {
    H1TestBars  = ReadTestBars( dir + "H1.txt" );
    M15TestBars = ReadTestBars( dir + "M15.txt" );
    M5TestBars  = ReadTestBars( dir + "M5.txt" );
    M1TestBars  = ReadTestBars( dir + "M1.txt" );
//    TestTicks   = ReadTestTicks( dir + "Ticks.txt" );
  }

  void PrintImportedFileTestData( std::vector<TestBar> bars)
  {
    std::cout << "Start Read..." << std::endl;
    for(std::vector<TestBar>::iterator it = bars.begin(); it != bars.end(); ++it) {
        std::cout << "bars: "
            << it->time << " "
            << it->timestamp << " "
            << it->open << " "
            << it->high << " "
            << it->low << " "
            << it->close << " "
            << it->maTotal << " "
            << it->ma << " "
            << it->stochMin << " "
            << it->stochMax << " "
            << it->stochK << " "
            << it->stochSlope << " "
            << it->fractalLow << " "
            << it->fractalHigh << " "
            << std::endl;
     }
    std::cout << "End..." << std::endl;

  }
} /* namespace pipware */

#endif /* PIPWARE_DATA_HELPER_HPP_ */
jcl wrote:I recently had to debug a C++ DLL for an Empty4 EA, but Empty4 crashes whenever I attach the VC++ debugger to the terminal.exe process. This seems to be due to some crude mechanism in Empty4 to prevent reverse engineering.

Has someone else run into the same problem? Is there a safe method to debug DLL functions called from an EA, or do I have to write some Empty4 simulator for that purpose?
Author:  stratman [ Tue Apr 02, 2013 8:40 pm ]
Post subject:  Re: How do you debug a Empty4 DLL?

I read the bars from the text file using

Code: Select all

  InitDataFromFiles( "D:\\dev\\git-pipware-dll\\Pipware-DLL\\tests-data\\" );
  dataFileTest( M1TestBars, Period::M1, "M1");
The data in the file looks like:

Code: Select all

1363752000 20130320_0400 1.50886 1.50887 1.50885 1.50885 28.19 1.50885 -1.00000 -1.00000 -1.00000 -1.00 -1.00 0 0
1363752060 20130320_0401 1.50884 1.50888 1.50881 1.50888 38.33 3.01773 -1.00000 -1.00000 -1.00000 -1.00 -1.00 0 0
1363752120 20130320_0402 1.50888 1.50888 1.50888 1.50888 9.00 4.52661 -1.00000 -1.00000 -1.00000 -1.00 -1.00 0 1
I pass my test data to the following function that checks that my DLL is calculating all indicators correctly. Fractals are a little complicated as they are lagging i.e. get formed on the 3rd bar back from current bar. This is why I use a queue.

I use eclipse for my dll programming and the CUTE unit testing framework. You can see how to use eclipse to develop Empty4 dlls on a thread I wrote at forex factory for that purpose.

Code: Select all

void BarCollection_Test::dataFileTest( std::vector<TestBar> testBars, Period::PeriodEnum period, std::string periodString )
{
  Bar *bar;

  long    count           = 0;
  int     fractalBarIndex = 1 + Config::FRACTAL_BARS/2;

  std::queue<bool> fractalLowQueue;
  std::queue<bool> fractalHighQueue;

  BarCollection<Bar> bars( period ,Config::CAPACITY );

  for(std::vector<TestBar>::iterator it = testBars.begin(); it != testBars.end(); ++it)
  {
    if ( count < Config::CAPACITY)
      ASSERT_EQUAL( count, bars._count );

    bar = new Bar(
        it->time,
        it->open,
        it->high,
        it->low,
        it->close,
        period);

    count++;
    std::cout << periodString << " count " << count << std::endl;

    bars.Push( *bar );
    delete bar;

    if ( count < Config::CAPACITY)
      ASSERT_EQUAL( count, bars._count );

    ASSERT_EQUAL( it->time, bars[0].Time() );
    ASSERT_EQUAL_DELTA( it->open, bars[0].Open(), 0.01 );
    ASSERT_EQUAL_DELTA( it->high, bars[0].High(), 0.01 );
    ASSERT_EQUAL_DELTA( it->low, bars[0].Low(), 0.01 );
    ASSERT_EQUAL_DELTA( it->close, bars[0].Close(), 0.01 );
    ASSERT_EQUAL_DELTA( it->maTotal, bars[0]._maTotal, 0.01 );
    ASSERT_EQUAL_DELTA( it->ma, bars[0].MA(), 0.01 );
    ASSERT_EQUAL_DELTA( it->stochMin, bars[0]._stochMin, 0.01 );
    ASSERT_EQUAL_DELTA( it->stochMax, bars[0]._stochMax, 0.01 );
    ASSERT_EQUAL_DELTA( it->stochK, bars[0].StochK(), 0.01 );
    ASSERT_EQUAL_DELTA( it->stochSlope, bars[0].StochSlope(), 0.01 );

    fractalLowQueue.push(bool(it->fractalLow==1));
    fractalHighQueue.push(bool(it->fractalHigh==1));

    if ( count > fractalBarIndex)
    {
      std::cout  << " fract low,high Q:" << fractalLowQueue.front() << "," << fractalHighQueue.front()
          << " C:" << bars[fractalBarIndex].IsFractalLow() << "," << bars[fractalBarIndex].IsFractalHigh() << std::endl;

      ASSERT_EQUAL( bars[fractalBarIndex].IsFractalLow(), fractalLowQueue.front() );
      ASSERT_EQUAL( bars[fractalBarIndex].IsFractalHigh(), fractalHighQueue.front() );

      fractalLowQueue.pop();
      fractalHighQueue.pop();
    }
    else
      std::cout << std::endl;
  }


}
Author:  jcl [ Sat Apr 13, 2013 11:34 am ]
Post subject:  Re: How do you debug a Empty4 DLL?

Thanks! I had meanwhile written a sort of Empty4 emulator for passing data to the DLL and debugging it.

Meanwhile, there are rumors that Metaquotes will disable not only debugging, but even using DLLs in their platform with one of the next updates...
All times are UTC Page 1 of 1