www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - demangle tool

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
I wrote a simple utility (at the bottom of this message) that may help 
debugging link-time errors. It reads lines from stdin and writes them 
with DMD symbols, if any, demangled.

For example, here's what you see if you add "alias field this;" to Tuple 
in std.typecons and try to build the "new, new" Phobos:

obj/posix/debug/unittest/std/file.o: In function 
`_D3std4file14__T5slurpTiTdZ5slurpFAyaxAaZAS3std8typecons14__T5TupleTiTdZ5Tuple':
/home/andrei/code/dmd/phobos/std/file.d:1772: undefined reference to 
`_D3std8typecons14__T5TupleTiTdZ5Tuple6__initZ'
/home/andrei/code/dmd/phobos/std/file.d:1781: undefined reference to 
`_D3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender3putMFxS3std8typecons14__T5TupleTiTdZ5TupleZv'
obj/posix/debug/unittest/std/file.o: In function 
`_D3std5array88__T8appenderTAS3std8typecons14__T5TupleTiTdZ5TupleTS3std8typecons14__T5TupleTiTdZ5TupleZ8appenderFPAS3std8typecons14__T5TupleTiTdZ5TupleZS3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender':
/home/andrei/code/dmd/phobos/std/array.d:578: undefined reference to 
`_D3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender6__ctorMFNcPAS3std8typecons14__T5TupleTiTdZ5TupleZS3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender'
obj/posix/debug/unittest/std/file.o: In function 
`_D3std8typecons14__T5tupleTiTdZ5tupleFidZS3std8typecons14__T5TupleTiTdZ5Tuple':
/home/andrei/code/dmd/phobos/std/typecons.d:515: undefined reference to 
`_D3std8typecons14__T5TupleTiTdZ5Tuple6__initZ'
collect2: ld returned 1 exit status
--- errorlevel 1

However, if you use "make |& ./demangle.d", you see:

obj/posix/debug/unittest/std/file.o: In function `struct 
std.typecons.Tuple!(int, double).Tuple[] std.file.slurp!(int, 
double).slurp(immutable(char)[], const(char[]))':
/home/andrei/code/dmd/phobos/std/file.d:1772: undefined reference to `Z 
std.typecons.Tuple!(int, double).Tuple.__init'
/home/andrei/code/dmd/phobos/std/file.d:1781: undefined reference to 
`void std.array.Appender!(struct std.typecons.Tuple!(int, 
double).Tuple[]).Appender.put(const(struct std.typecons.Tuple!(int, 
double).Tuple))'
obj/posix/debug/unittest/std/file.o: In function `struct 
std.array.Appender!(struct std.typecons.Tuple!(int, 
double).Tuple[]).Appender std.array.appender!(struct 
std.typecons.Tuple!(int, double).Tuple[], struct 
std.typecons.Tuple!(int, double).Tuple).appender(struct 
std.typecons.Tuple!(int, double).Tuple[]*)':
/home/andrei/code/dmd/phobos/std/array.d:578: undefined reference to 
`_D3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender6__ctorMFNcPAS3std8typecons14__T5TupleTiTdZ5TupleZS3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender'
obj/posix/debug/unittest/std/file.o: In function `struct 
std.typecons.Tuple!(int, double).Tuple std.typecons.tuple!(int, 
double).tuple(int, double)':
/home/andrei/code/dmd/phobos/std/typecons.d:515: undefined reference to 
`Z std.typecons.Tuple!(int, double).Tuple.__init'
collect2: ld returned 1 exit status
--- errorlevel 1
make: *** [obj/posix/debug/unittest/std/file] Error 1

The line wraps are all garbled, but you get the idea: all symbols quoted 
`like this' have been demangled appropriately. Below is the source of 
the demangle script:


import std.algorithm, std.demangle, std.getopt, std.stdio;

void main(string[] args)
{
     string lSep = "`", rSep = "'";
     getopt(args, "lsep", &lSep, "rsep", &rSep);
     foreach (line; stdin.byLine())
     {
         auto sym = find(line, lSep);
         if (!sym.length)
         {
             writeln(line);
             continue;
         }
         sym = sym[1 .. $];
         auto before = line[0 .. $ - sym.length];
         sym = sym[0 .. $ - find(sym, rSep).length];
         auto after = line[before.length + sym.length .. $];
         writeln(before, demangle(sym.idup), after);
     }
}


Hope this helps someone,

Andrei
Apr 09 2009
next sibling parent reply grauzone <none example.net> writes:
I wrote something like that, like what, years ago?

Debugging D programs with the current toolchain is a serious pain in the 
ass, but a demangler makes it a bit more tolerable.

By the way, is the current std.demangle functionally complete?
Apr 09 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
grauzone wrote:
 I wrote something like that, like what, years ago?
 
 Debugging D programs with the current toolchain is a serious pain in the 
 ass, but a demangler makes it a bit more tolerable.
 
 By the way, is the current std.demangle functionally complete?
No idea. Andrei
Apr 09 2009
prev sibling parent Leandro Lucarella <llucax gmail.com> writes:
grauzone, el  9 de abril a las 23:33 me escribiste:
 I wrote something like that, like what, years ago?
 
 Debugging D programs with the current toolchain is a serious pain in the ass,
but a demangler makes it a bit more tolerable.
 
 By the way, is the current std.demangle functionally complete?
There is even an example program that does this in the std.demangle module documentation[1], even for D2[2] ;) Maybe the D2 example can be changed for this program, that is more D2-ish. [1] http://www.digitalmars.com/d/1.0/phobos/std_demangle.html [2] http://www.digitalmars.com/d/2.0/phobos/std_demangle.html -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- There is no pain you are receding A distant ship, smoke on the horizon. You are only coming through in waves. Your lips move but I can't hear what you're saying.
Apr 09 2009
prev sibling next sibling parent reply R <a b.com> writes:
Hurm. I thought one of the things D had over C++ was that with aliases such
complex error messages can be avoided. While D still seems to be better off
than C++ I guess something like this is unavoidable with metaprogramming?

Andrei Alexandrescu Wrote:

 I wrote a simple utility (at the bottom of this message) that may help 
 debugging link-time errors. It reads lines from stdin and writes them 
 with DMD symbols, if any, demangled.
 
 For example, here's what you see if you add "alias field this;" to Tuple 
 in std.typecons and try to build the "new, new" Phobos:
 
 obj/posix/debug/unittest/std/file.o: In function 
 `_D3std4file14__T5slurpTiTdZ5slurpFAyaxAaZAS3std8typecons14__T5TupleTiTdZ5Tuple':
 /home/andrei/code/dmd/phobos/std/file.d:1772: undefined reference to 
 `_D3std8typecons14__T5TupleTiTdZ5Tuple6__initZ'
 /home/andrei/code/dmd/phobos/std/file.d:1781: undefined reference to 
 `_D3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender3putMFxS3std8typecons14__T5TupleTiTdZ5TupleZv'
 obj/posix/debug/unittest/std/file.o: In function 
 `_D3std5array88__T8appenderTAS3std8typecons14__T5TupleTiTdZ5TupleTS3std8typecons14__T5TupleTiTdZ5TupleZ8appenderFPAS3std8typecons14__T5TupleTiTdZ5TupleZS3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender':
 /home/andrei/code/dmd/phobos/std/array.d:578: undefined reference to 
 `_D3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender6__ctorMFNcPAS3std8typecons14__T5TupleTiTdZ5TupleZS3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender'
 obj/posix/debug/unittest/std/file.o: In function 
 `_D3std8typecons14__T5tupleTiTdZ5tupleFidZS3std8typecons14__T5TupleTiTdZ5Tuple':
 /home/andrei/code/dmd/phobos/std/typecons.d:515: undefined reference to 
 `_D3std8typecons14__T5TupleTiTdZ5Tuple6__initZ'
 collect2: ld returned 1 exit status
 --- errorlevel 1
 
 However, if you use "make |& ./demangle.d", you see:
 
 obj/posix/debug/unittest/std/file.o: In function `struct 
 std.typecons.Tuple!(int, double).Tuple[] std.file.slurp!(int, 
 double).slurp(immutable(char)[], const(char[]))':
 /home/andrei/code/dmd/phobos/std/file.d:1772: undefined reference to `Z 
 std.typecons.Tuple!(int, double).Tuple.__init'
 /home/andrei/code/dmd/phobos/std/file.d:1781: undefined reference to 
 `void std.array.Appender!(struct std.typecons.Tuple!(int, 
 double).Tuple[]).Appender.put(const(struct std.typecons.Tuple!(int, 
 double).Tuple))'
 obj/posix/debug/unittest/std/file.o: In function `struct 
 std.array.Appender!(struct std.typecons.Tuple!(int, 
 double).Tuple[]).Appender std.array.appender!(struct 
 std.typecons.Tuple!(int, double).Tuple[], struct 
 std.typecons.Tuple!(int, double).Tuple).appender(struct 
 std.typecons.Tuple!(int, double).Tuple[]*)':
 /home/andrei/code/dmd/phobos/std/array.d:578: undefined reference to 
 `_D3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender6__ctorMFNcPAS3std8typecons14__T5TupleTiTdZ5TupleZS3std5array51__T8AppenderTAS3std8typecons14__T5TupleTiTdZ5TupleZ8Appender'
 obj/posix/debug/unittest/std/file.o: In function `struct 
 std.typecons.Tuple!(int, double).Tuple std.typecons.tuple!(int, 
 double).tuple(int, double)':
 /home/andrei/code/dmd/phobos/std/typecons.d:515: undefined reference to 
 `Z std.typecons.Tuple!(int, double).Tuple.__init'
 collect2: ld returned 1 exit status
 --- errorlevel 1
 make: *** [obj/posix/debug/unittest/std/file] Error 1
 
 The line wraps are all garbled, but you get the idea: all symbols quoted 
 `like this' have been demangled appropriately. Below is the source of 
 the demangle script:
 

 import std.algorithm, std.demangle, std.getopt, std.stdio;
 
 void main(string[] args)
 {
      string lSep = "`", rSep = "'";
      getopt(args, "lsep", &lSep, "rsep", &rSep);
      foreach (line; stdin.byLine())
      {
          auto sym = find(line, lSep);
          if (!sym.length)
          {
              writeln(line);
              continue;
          }
          sym = sym[1 .. $];
          auto before = line[0 .. $ - sym.length];
          sym = sym[0 .. $ - find(sym, rSep).length];
          auto after = line[before.length + sym.length .. $];
          writeln(before, demangle(sym.idup), after);
      }
 }
 
 
 Hope this helps someone,
 
 Andrei
Apr 10 2009
parent bearophile <bearophileHUGS lycos.com> writes:
R:
While D still seems to be better off than C++ I guess something like this is
unavoidable with metaprogramming?<
Lot of people have discussed about this topic, and some of them have even found some partial solutions, for example: http://www.ddj.com/cpp/184401416?pgno=1 Of course Andrei was among them :-) Some of those ideas can be implemented in a native way into the D compiler. Bye, bearophile
Apr 10 2009
prev sibling next sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Thu, 09 Apr 2009 13:40:36 -0700, Andrei Alexandrescu wrote:

 The line wraps are all garbled, but you get the idea: all symbols quoted 
 `like this' have been demangled appropriately. Below is the source of 
 the demangle script:
 

 import std.algorithm, std.demangle, std.getopt, std.stdio;
 
 void main(string[] args)
 {
      string lSep = "`", rSep = "'";
      getopt(args, "lsep", &lSep, "rsep", &rSep);
      foreach (line; stdin.byLine())
      {
          auto sym = find(line, lSep);
          if (!sym.length)
          {
              writeln(line);
              continue;
          }
          sym = sym[1 .. $];
          auto before = line[0 .. $ - sym.length];
          sym = sym[0 .. $ - find(sym, rSep).length];
          auto after = line[before.length + sym.length .. $];
          writeln(before, demangle(sym.idup), after);
      }
 }
What happened to the range boolean operations, those before/after/whatever? Do you still plan to implement them?
Apr 10 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Sergey Gromov wrote:
 Thu, 09 Apr 2009 13:40:36 -0700, Andrei Alexandrescu wrote:
 
 The line wraps are all garbled, but you get the idea: all symbols quoted 
 `like this' have been demangled appropriately. Below is the source of 
 the demangle script:


 import std.algorithm, std.demangle, std.getopt, std.stdio;

 void main(string[] args)
 {
      string lSep = "`", rSep = "'";
      getopt(args, "lsep", &lSep, "rsep", &rSep);
      foreach (line; stdin.byLine())
      {
          auto sym = find(line, lSep);
          if (!sym.length)
          {
              writeln(line);
              continue;
          }
          sym = sym[1 .. $];
          auto before = line[0 .. $ - sym.length];
          sym = sym[0 .. $ - find(sym, rSep).length];
          auto after = line[before.length + sym.length .. $];
          writeln(before, demangle(sym.idup), after);
      }
 }
What happened to the range boolean operations, those before/after/whatever? Do you still plan to implement them?
Curiously, I didn't find a need for them in std.algorithm so far. I only defined sameHead, and that's only to help a little improvement in the bringToFront algorithm. Andrei
Apr 10 2009
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-04-10 17:25:30 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Curiously, I didn't find a need for them in std.algorithm so far. I 
 only defined sameHead, and that's only to help a little improvement in 
 the bringToFront algorithm.
I've written a few parsers where I repeat this pattern a lot: string read(alias consumer)(ref string input) { string value = input; consumer(input); return value.before(input); } And I like very much how it reads: "text before input". All this done on D1. Perhaps it'd need to be revamped a little for D2. Here's my implementation if you're interested. T[] after(T)(T[] r, T[] s) in { assert(s.ptr >= r.ptr && s.ptr <= r.ptr + r.length); } body { char* begin = s.ptr + s.length; char* end = r.ptr + r.length; return begin[0..end-begin]; } T[] before(T)(T[] r, T[] s) in { assert(s.ptr >= r.ptr && s.ptr <= r.ptr + r.length); } body { char* begin = r.ptr; char* end = s.ptr; return begin[0..end-begin]; } unittest { string a = "abcdef"; string b = a[1..3]; // bc assert(a.after(b) == "def"); assert(a.before(b) == "a"); string c = a[3..3]; // empty string assert(a.after(c) == "def"); assert(a.before(c) == "abc"); string d = a[0..$]; // same string assert(a.after(d) == ""); assert(a.before(d) == ""); } -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Apr 10 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2009-04-10 17:25:30 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Curiously, I didn't find a need for them in std.algorithm so far. I 
 only defined sameHead, and that's only to help a little improvement in 
 the bringToFront algorithm.
I've written a few parsers where I repeat this pattern a lot: string read(alias consumer)(ref string input) { string value = input; consumer(input); return value.before(input); } And I like very much how it reads: "text before input". All this done on D1. Perhaps it'd need to be revamped a little for D2. Here's my implementation if you're interested.
[snip] Thanks. Arrays aren't a problem, but non-random-access ranges are problematic. (For arrays a slice could also be taken.) That's why I've been reluctant - if I make before and after primitives, then anyone defining a range needs to worry about implementing them. Andrei
Apr 10 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-04-11 00:00:08 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Thanks. Arrays aren't a problem, but non-random-access ranges are 
 problematic. (For arrays a slice could also be taken.) That's why I've 
 been reluctant - if I make before and after primitives, then anyone 
 defining a range needs to worry about implementing them.
Then could it be limited to random-access ranges? Other ranges could provide their own implementation, if it makes sense for them. That'd make another category of ranges: "intersectable ranges". We could just provide primitives for consuming a range and returning the consumed data (as my read function does above). This could be supported by all ranges. Which makes me think: how does the new regex library handle consuming and backtracking with ranges? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Apr 11 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2009-04-11 00:00:08 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Thanks. Arrays aren't a problem, but non-random-access ranges are 
 problematic. (For arrays a slice could also be taken.) That's why I've 
 been reluctant - if I make before and after primitives, then anyone 
 defining a range needs to worry about implementing them.
Then could it be limited to random-access ranges? Other ranges could provide their own implementation, if it makes sense for them. That'd make another category of ranges: "intersectable ranges". We could just provide primitives for consuming a range and returning the consumed data (as my read function does above). This could be supported by all ranges. Which makes me think: how does the new regex library handle consuming and backtracking with ranges?
For now regex only supports random-access ranges. Andrei
Apr 11 2009
prev sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Fri, 10 Apr 2009 14:25:30 -0700, Andrei Alexandrescu wrote:

 Sergey Gromov wrote:
 Thu, 09 Apr 2009 13:40:36 -0700, Andrei Alexandrescu wrote:
 
 The line wraps are all garbled, but you get the idea: all symbols quoted 
 `like this' have been demangled appropriately. Below is the source of 
 the demangle script:


 import std.algorithm, std.demangle, std.getopt, std.stdio;

 void main(string[] args)
 {
      string lSep = "`", rSep = "'";
      getopt(args, "lsep", &lSep, "rsep", &rSep);
      foreach (line; stdin.byLine())
      {
          auto sym = find(line, lSep);
          if (!sym.length)
          {
              writeln(line);
              continue;
          }
          sym = sym[1 .. $];
          auto before = line[0 .. $ - sym.length];
          sym = sym[0 .. $ - find(sym, rSep).length];
          auto after = line[before.length + sym.length .. $];
          writeln(before, demangle(sym.idup), after);
      }
 }
What happened to the range boolean operations, those before/after/whatever? Do you still plan to implement them?
Curiously, I didn't find a need for them in std.algorithm so far. I only defined sameHead, and that's only to help a little improvement in the bringToFront algorithm.
I asked because I thought that "blah[foo.length .. $ - bar.length]" stuff wasn't very nice. Compare: sym.advance; // popFront, or sym[1 .. $] auto s1 = line.before(sym); auto s3 = find(sym, rSep); writeln(s1, demangle(sym.before(s3).idup), s3);
Apr 12 2009
prev sibling parent reply Jason House <jason.james.house gmail.com> writes:
It looks useful, especially when using rdmd.  Why does rdmd require that the 
file end in .d?  That seems limiting, especially when I want to make an 
executable file that looks like other executables in linux...  aka no 
extension at all.

Andrei Alexandrescu wrote:

 I wrote a simple utility (at the bottom of this message) that may help
 debugging link-time errors. It reads lines from stdin and writes them
 with DMD symbols, if any, demangled.
Apr 10 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jason House wrote:
 It looks useful, especially when using rdmd.  Why does rdmd require that the 
 file end in .d?  That seems limiting, especially when I want to make an 
 executable file that looks like other executables in linux...  aka no 
 extension at all.
 
 Andrei Alexandrescu wrote:
 
 I wrote a simple utility (at the bottom of this message) that may help
 debugging link-time errors. It reads lines from stdin and writes them
 with DMD symbols, if any, demangled.
Good point. Also zsh-style streams <(...) could be supported. Any chance you could take a minute to submit a bug report? I'll take care of it when I have time. Andrei
Apr 10 2009