unmangler 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -61,7 +61,11 @@ class StringPtr
61
61
  end
62
62
 
63
63
  def index needle
64
- @string[@pos..-1].index(needle)
64
+ (@string[@pos..-1] || '').index(needle)
65
+ end
66
+
67
+ def strlen
68
+ (@string[@pos..-1] || '').bytesize
65
69
  end
66
70
 
67
71
  def =~ re
@@ -71,6 +75,23 @@ class StringPtr
71
75
  def inc!; @pos+=1; end
72
76
  def dec!; @pos-=1; end
73
77
 
78
+ # get current character and then increment
79
+ # like in C:
80
+ # c = *p++
81
+ def get_inc!
82
+ c = @string[@pos]
83
+ @pos+=1
84
+ c
85
+ end
86
+
87
+ # increment and then get current character
88
+ # like in C:
89
+ # c = *++p
90
+ def inc_get!
91
+ @pos+=1
92
+ @string[@pos]
93
+ end
94
+
74
95
  def trim!
75
96
  return unless @string
76
97
  if idx = @string.index("\x00")
@@ -94,6 +115,10 @@ class StringPtr
94
115
  @pos - x.pos
95
116
  end
96
117
  end
118
+
119
+ def inspect
120
+ "#<StringPtr @pos=#{@pos.inspect}: #{@string[@pos..-1].inspect}>"
121
+ end
97
122
  end
98
123
 
99
124
  if $0 == __FILE__
@@ -1,3 +1,3 @@
1
1
  module Unmangler
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unmangler::Borland do
4
+ if max_idx = ENV['LONG_RUN']
5
+ max_idx = max_idx.to_i
6
+ idx = 0
7
+ YAML::load_file(File.join(SAMPLES_DIR, "borland.yaml")).each do |mangled, unmangled|
8
+ unmangled = preprocess_borland unmangled
9
+ idx += 1
10
+ break if idx > max_idx
11
+ it "should unmangle #{mangled}" do
12
+ Unmangler::Borland.unmangle(mangled).should == unmangled
13
+ end
14
+ end
15
+ else
16
+ it "should unmangle" do
17
+ YAML::load_file(File.join(SAMPLES_DIR, "borland.yaml")).each do |mangled, unmangled|
18
+ unmangled = preprocess_borland unmangled
19
+ actual = Unmangler::Borland.unmangle(mangled)
20
+ actual.should eql(unmangled), [
21
+ "mangled : #{mangled.white}",
22
+ "expected: #{unmangled.green}",
23
+ "actual : #{actual.red}"
24
+ ].join("\n")
25
+ end
26
+ end
27
+ end
28
+ end
@@ -70,4 +70,6 @@ describe Unmangler::Borland do
70
70
  check "@Dbcommon@GetTableNameFromSQLEx$qqrx17System@WideString25Dbcommon@IDENTIFIEROption",
71
71
  "__fastcall Dbcommon::GetTableNameFromSQLEx(const System::WideString, Dbcommon::IDENTIFIEROption)"
72
72
 
73
+ check '@Classes@TThread@$bcdtr$qqrv', '__fastcall Classes::TThread::`class destructor`()'
74
+ check '@Timespan@TTimeSpan@$bcctr$qqrv', '__fastcall Timespan::TTimeSpan::`class constructor`()'
73
75
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unmangler::MSVC do
4
+ if max_idx = ENV['LONG_RUN']
5
+ max_idx = max_idx.to_i
6
+ idx = 0
7
+ YAML::load_file(File.join(SAMPLES_DIR, "msvc.yaml")).each do |mangled, unmangled|
8
+ idx += 1
9
+ break if idx > max_idx
10
+ it "should unmangle #{mangled}" do
11
+ unmangled = preprocess_msvc unmangled
12
+ Unmangler::MSVC.unmangle(mangled).should == unmangled
13
+ end
14
+ end
15
+ else
16
+ it "should unmangle" do
17
+ YAML::load_file(File.join(SAMPLES_DIR, "msvc.yaml")).each do |mangled, unmangled|
18
+ unmangled = preprocess_msvc unmangled
19
+ actual = Unmangler::MSVC.unmangle(mangled)
20
+ actual.should eql(unmangled), [
21
+ "mangled : #{mangled.white}",
22
+ "expected: #{unmangled.green}",
23
+ "actual : #{actual.red}"
24
+ ].join("\n")
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unmangler::MSVC do
4
+
5
+ it "keeps original name if not mangled" do
6
+ s = "foo::bar(@)"
7
+ Unmangler::MSVC.unmangle(s).should == s
8
+ end
9
+
10
+ # describe "#unmangle" do
11
+ # it "raises error on bad input" do
12
+ # lambda{
13
+ # Unmangler::MSVC.unmangle("@TTabPage@$bctr")
14
+ # }.should raise_error
15
+ # end
16
+ # end
17
+
18
+ describe "#safe_unmangle" do
19
+ it "raises no error and returns original on bad input" do
20
+ s = "@TTabPage@$bctr"
21
+ Unmangler::MSVC.safe_unmangle(s).should == s
22
+ end
23
+ end
24
+
25
+ def self.check mangled, unmangled, test_no_args = true
26
+ it "unmangles #{mangled}" do
27
+ Unmangler::MSVC.unmangle(mangled).should == unmangled
28
+ end
29
+
30
+ it "unmangles #{mangled} w/o args" do
31
+ x = unmangled.split('(').first.strip.
32
+ gsub(/(public|private|protected): /,'').
33
+ gsub(/(void|__ptr64|int|__thiscall|__cdecl|virtual|class|struct) /,'').
34
+ strip
35
+
36
+ Unmangler::MSVC.unmangle(mangled, :args => false).should == x
37
+ end if test_no_args
38
+ end
39
+
40
+ check "?h@@YAXH@Z", "void __cdecl h(int)"
41
+ check "?AFXSetTopLevelFrame@@YAXPAVCFrameWnd@@@Z", "void __cdecl AFXSetTopLevelFrame(class CFrameWnd *)"
42
+ check "??0_Lockit@std@@QAE@XZ", "public: __thiscall std::_Lockit::_Lockit(void)"
43
+
44
+ check "?SetAt@CString@@QAEXHD@Z", "public: void __thiscall CString::SetAt(int, char)"
45
+ check "?LoadFrame@CMDIFrameWndEx@@UAEHIKPAVCWnd@@PAUCCreateContext@@@Z",
46
+ "public: virtual int __thiscall CMDIFrameWndEx::LoadFrame(unsigned int, unsigned long, class CWnd *, struct CCreateContext *)"
47
+
48
+ check "??0DNameStatusNode@@AEAA@W4DNameStatus@@@Z",
49
+ "private: __cdecl DNameStatusNode::DNameStatusNode(enum DNameStatus) __ptr64"
50
+
51
+ check "?Add@?$CArray@VCSize@@V1@@@QAEHVCSize@@@Z",
52
+ "public: int __thiscall CArray<class CSize, class CSize>::Add(class CSize)"
53
+
54
+ check "??$_Char_traits_cat@U?$char_traits@D@std@@@std@@YA?AU_Secure_char_traits_tag@0@XZ",
55
+ "struct std::_Secure_char_traits_tag __cdecl std::_Char_traits_cat<struct std::char_traits<char> >(void)",
56
+ false
57
+
58
+ check "?dtor$0@?0???0CDockSite@@QEAA@XZ@4HA",
59
+ "int `public: __cdecl CDockSite::CDockSite(void) __ptr64'::`1'::dtor$0",
60
+ false
61
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ def combined_samples
4
+ @@combined_samples ||=
5
+ begin
6
+ msvc = YAML::load_file(File.join(SAMPLES_DIR, "msvc.yaml"))
7
+ borland = YAML::load_file(File.join(SAMPLES_DIR, "borland.yaml"))
8
+
9
+ combined = {}
10
+ (msvc.keys + borland.keys).uniq.each do |key|
11
+ um = msvc[key]
12
+ ub = borland[key]
13
+
14
+ combined[key] =
15
+ if um && um != key
16
+ preprocess_msvc um
17
+ elsif ub && ub != key
18
+ preprocess_borland ub
19
+ else
20
+ # neither
21
+ key
22
+ end
23
+ end
24
+ combined
25
+ end
26
+ end
27
+
28
+ describe Unmangler do
29
+ if max_idx = ENV['LONG_RUN']
30
+ max_idx = max_idx.to_i
31
+ idx = 0
32
+ combined_samples.each do |mangled, unmangled|
33
+ idx += 1
34
+ break if idx > max_idx
35
+ it "should unmangle #{mangled}" do
36
+ Unmangler.unmangle(mangled).should == unmangled
37
+ end
38
+ end
39
+ else
40
+ it "should unmangle" do
41
+ combined_samples.each do |mangled, unmangled|
42
+ actual = Unmangler.unmangle(mangled)
43
+ actual.should eql(unmangled), [
44
+ "mangled : #{mangled.white}",
45
+ "expected: #{unmangled.green}",
46
+ "actual : #{actual.red}"
47
+ ].join("\n")
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,14 +1,39 @@
1
+ require 'yaml'
2
+ require 'awesome_print'
3
+
1
4
  $: << File.expand_path("../lib", File.dirname(__FILE__))
2
5
  require 'unmangler'
3
6
 
7
+ SAMPLES_DIR = File.expand_path("../samples", File.dirname(__FILE__))
8
+
9
+ def preprocess_msvc s
10
+ s.gsub(',',', ')
11
+ end
12
+
13
+ def preprocess_borland s
14
+ r = s.gsub('const const ','const ')
15
+
16
+ # move '__fastcall' to start of the string if its found in middle of string
17
+ pos = r.index(" __fastcall ")
18
+ if pos && pos != 0
19
+ r = "__fastcall " + r.sub("__fastcall ", "")
20
+ end
21
+
22
+ r
23
+ end
24
+
4
25
  RSpec.configure do |config|
5
26
  config.treat_symbols_as_metadata_keys_with_true_values = true
6
27
  config.run_all_when_everything_filtered = true
7
- #config.filter_run :focus
8
28
 
9
- # Run specs in random order to surface order dependencies. If you find an
10
- # order dependency and want to debug it, you can fix the order by providing
11
- # the seed, which is printed after each run.
12
- # --seed 1234
13
- #config.order = 'random'
29
+ config.before(:suite) do
30
+ Dir[File.join(SAMPLES_DIR, "*.bz2")].each do |fname|
31
+ unless File.exist?(fname.sub(/\.bz2$/,''))
32
+ puts "[.] unpacking #{fname} .."
33
+ system("bunzip2", "-dk", fname)
34
+ end
35
+ end
36
+ end
37
+
38
+ config.backtrace_clean_patterns = [/\/rspec/]
14
39
  end
@@ -12,7 +12,9 @@ Gem::Specification.new do |gem|
12
12
  gem.summary = gem.description + %q{, i.e. '@myclass@func$qil' => 'myclass::func(int, long)'}
13
13
  gem.homepage = "http://zed.0xff.me"
14
14
 
15
- gem.files = `git ls-files`.split($/)
15
+ gem.files = `git ls-files`.split($/).
16
+ delete_if{ |x| x.end_with?(".bz2") || x.include?("misc/") }
17
+
16
18
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
19
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
20
  gem.require_paths = ["lib"]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unmangler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey "Zed" Zaikin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-03 00:00:00.000000000 Z
11
+ date: 2013-05-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Unmangles mangled C++/Delphi names"
14
14
  email:
@@ -25,10 +25,16 @@ files:
25
25
  - README.md.tpl
26
26
  - Rakefile
27
27
  - lib/unmangler.rb
28
+ - lib/unmangler/base.rb
28
29
  - lib/unmangler/borland.rb
30
+ - lib/unmangler/msvc.rb
29
31
  - lib/unmangler/string_ptr.rb
30
32
  - lib/unmangler/version.rb
33
+ - spec/borland_samples_spec.rb
31
34
  - spec/borland_spec.rb
35
+ - spec/msvc_samples_spec.rb
36
+ - spec/msvc_spec.rb
37
+ - spec/samples_spec.rb
32
38
  - spec/spec_helper.rb
33
39
  - unmangler.gemspec
34
40
  homepage: http://zed.0xff.me
@@ -56,5 +62,9 @@ specification_version: 4
56
62
  summary: Unmangles mangled C++/Delphi names", i.e. '@myclass@func$qil' => 'myclass::func(int,
57
63
  long)'
58
64
  test_files:
65
+ - spec/borland_samples_spec.rb
59
66
  - spec/borland_spec.rb
67
+ - spec/msvc_samples_spec.rb
68
+ - spec/msvc_spec.rb
69
+ - spec/samples_spec.rb
60
70
  - spec/spec_helper.rb