unmangler 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ class StringPtr
4
+ attr_accessor :string, :pos
5
+
6
+ def initialize s=nil, pos=0
7
+ case s
8
+ when String
9
+ @string = s
10
+ @pos = pos
11
+ when StringPtr
12
+ @string = s.string
13
+ @pos = s.pos + pos
14
+ when NilClass
15
+ @string = nil
16
+ @pos = pos
17
+ else
18
+ raise "invalid s: #{s.inspect}"
19
+ end
20
+ end
21
+
22
+ def [] pos, len=nil
23
+ if t = @string[@pos..-1]
24
+ if len
25
+ t[pos, len]
26
+ else
27
+ t[pos]
28
+ end
29
+ else
30
+ nil
31
+ end
32
+ end
33
+
34
+ def []= pos, x, y=nil
35
+ if y
36
+ # s[10, 3] = 'abc'
37
+ @string[@pos+pos, x] = y
38
+ elsif pos.is_a?(Range)
39
+ range = pos
40
+ if range.end > 0
41
+ # s[10..12] = 'abc'
42
+ @string[Range.new(range.begin+@pos, range.end+@pos)] = x
43
+ else
44
+ if range.begin >= 0
45
+ # s[10..-1] = 'abc'
46
+ @string[Range.new(range.begin+@pos, range.end)] = x
47
+ else
48
+ # s[-3..-1] = 'abc'
49
+ @string[range] = x
50
+ end
51
+ end
52
+ else
53
+ # s[10] = 'a'
54
+ @string[@pos+pos] = x
55
+ end
56
+ end
57
+
58
+ def << s
59
+ @string[@pos, s.size] = s
60
+ @pos += s.size
61
+ end
62
+
63
+ def index needle
64
+ @string[@pos..-1].index(needle)
65
+ end
66
+
67
+ def =~ re
68
+ @string[@pos..-1] =~ re
69
+ end
70
+
71
+ def inc!; @pos+=1; end
72
+ def dec!; @pos-=1; end
73
+
74
+ def trim!
75
+ return unless @string
76
+ if idx = @string.index("\x00")
77
+ @string[idx..-1] = ''
78
+ @pos = @string.size if @pos > @string.size
79
+ end
80
+ end
81
+
82
+ def + n
83
+ self.class.new @string, @pos+n
84
+ end
85
+
86
+ def - x
87
+ case x
88
+ when Numeric
89
+ # shift pointer
90
+ self.class.new @string, @pos-x
91
+ when StringPtr
92
+ # return diff btw 2 ptrs
93
+ raise "subtracting different pointers" if self.string != x.string
94
+ @pos - x.pos
95
+ end
96
+ end
97
+ end
98
+
99
+ if $0 == __FILE__
100
+ ptr = StringPtr.new("foo")
101
+ p ptr[0]
102
+ p ptr[1]
103
+ p ptr
104
+ ptr += 1
105
+ p ptr
106
+ p ptr[0]
107
+
108
+ p2 = ptr+4
109
+ p ptr-p2
110
+ p p2-ptr
111
+ p ptr-1
112
+ end
@@ -0,0 +1,3 @@
1
+ module Unmangler
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unmangler::Borland do
4
+
5
+ it "keeps original name if not mangled" do
6
+ s = "foo::bar(@)"
7
+ Unmangler::Borland.unmangle(s).should == s
8
+ end
9
+
10
+ describe "#unmangle" do
11
+ it "raises error on bad input" do
12
+ lambda{
13
+ Unmangler::Borland.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::Borland.safe_unmangle(s).should == s
22
+ end
23
+ end
24
+
25
+ def self.check mangled, unmangled
26
+ it "unmangles #{mangled}" do
27
+ Unmangler::Borland.unmangle(mangled).should == unmangled
28
+ end
29
+
30
+ it "unmangles #{mangled} w/o args" do
31
+ x = unmangled.split('(').first.strip.sub(/^__fastcall /,'')
32
+ Unmangler::Borland.unmangle(mangled, :args => false).should == x
33
+ end
34
+ end
35
+
36
+ check "@afunc$qxzcupi", "afunc(const signed char, int *)"
37
+ check "@foo$qpqfi$d", "foo(double (*)(float, int))"
38
+ check "@myclass@func$qil","myclass::func(int, long)"
39
+
40
+ check "@Sysinit@@InitExe$qqrpv",
41
+ "__fastcall Sysinit::__linkproc__ InitExe(void *)"
42
+
43
+ check "@Forms@TApplication@SetTitle$qqrx17System@AnsiString",
44
+ "__fastcall Forms::TApplication::SetTitle(const System::AnsiString)"
45
+
46
+ check "@Forms@TApplication@CreateForm$qqrp17System@TMetaClasspv",
47
+ "__fastcall Forms::TApplication::CreateForm(System::TMetaClass *, void *)"
48
+
49
+ check "@System@@LStrCatN$qqrv", "__fastcall System::__linkproc__ LStrCatN()"
50
+
51
+ check "@System@DynArraySetLength$qqrrpvpvipi",
52
+ "__fastcall System::DynArraySetLength(void *&, void *, int, int *)"
53
+
54
+ check "@System@Variant@PutElement$qqrrx14System@Variantxixi",
55
+ "__fastcall System::Variant::PutElement(System::Variant&, const int, const int)"
56
+
57
+ check "@Windows@HwndMSWheel$qqrruit1t1rit4",
58
+ "__fastcall Windows::HwndMSWheel(unsigned int&, unsigned int&, unsigned int&, int&, int&)"
59
+
60
+ # IDA uses '__int64' instead of 'long long'
61
+ check "@Sysutils@TryStrToInt64$qqrx17System@AnsiStringrj",
62
+ "__fastcall Sysutils::TryStrToInt64(const System::AnsiString, long long&)"
63
+
64
+ check "@Sysutils@Supports$qqrpx14System@TObjectrx5_GUIDpv",
65
+ "__fastcall Sysutils::Supports(System::TObject *, _GUID&, void *)"
66
+
67
+ check "@std@%vector$51boost@archive@detail@basic_iarchive_impl@cobject_id69std@%allocator$51boost@archive@detail@basic_iarchive_impl@cobject_id%%@$bsubs$qui",
68
+ "std::vector<boost::archive::detail::basic_iarchive_impl::cobject_id, std::allocator<boost::archive::detail::basic_iarchive_impl::cobject_id> >::operator [](unsigned int)"
69
+
70
+ check "@Dbcommon@GetTableNameFromSQLEx$qqrx17System@WideString25Dbcommon@IDENTIFIEROption",
71
+ "__fastcall Dbcommon::GetTableNameFromSQLEx(const System::WideString, Dbcommon::IDENTIFIEROption)"
72
+
73
+ end
@@ -0,0 +1,14 @@
1
+ $: << File.expand_path("../lib", File.dirname(__FILE__))
2
+ require 'unmangler'
3
+
4
+ RSpec.configure do |config|
5
+ config.treat_symbols_as_metadata_keys_with_true_values = true
6
+ config.run_all_when_everything_filtered = true
7
+ #config.filter_run :focus
8
+
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'
14
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'unmangler/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "unmangler"
8
+ gem.version = Unmangler::VERSION
9
+ gem.authors = ["Andrey \"Zed\" Zaikin"]
10
+ gem.email = ["zed.0xff@gmail.com"]
11
+ gem.description = %q{Unmangles mangled C++/Delphi names"}
12
+ gem.summary = gem.description + %q{, i.e. '@myclass@func$qil' => 'myclass::func(int, long)'}
13
+ gem.homepage = "http://zed.0xff.me"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unmangler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrey "Zed" Zaikin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-03 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Unmangles mangled C++/Delphi names"
14
+ email:
15
+ - zed.0xff@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .gitignore
21
+ - .rspec
22
+ - Gemfile
23
+ - LICENSE.txt
24
+ - README.md
25
+ - README.md.tpl
26
+ - Rakefile
27
+ - lib/unmangler.rb
28
+ - lib/unmangler/borland.rb
29
+ - lib/unmangler/string_ptr.rb
30
+ - lib/unmangler/version.rb
31
+ - spec/borland_spec.rb
32
+ - spec/spec_helper.rb
33
+ - unmangler.gemspec
34
+ homepage: http://zed.0xff.me
35
+ licenses: []
36
+ metadata: {}
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubyforge_project:
53
+ rubygems_version: 2.0.3
54
+ signing_key:
55
+ specification_version: 4
56
+ summary: Unmangles mangled C++/Delphi names", i.e. '@myclass@func$qil' => 'myclass::func(int,
57
+ long)'
58
+ test_files:
59
+ - spec/borland_spec.rb
60
+ - spec/spec_helper.rb