Du bist hier: Skip Navigation LinksHome > .NET > LIB-Viewer

LIB Viewer - .h-Dateien exportieren

Einleitung

Haben Sie sich schon einmal gefragt, welche Funktionen eine Bibliothek (.lib) exportiert? Manchmal beinhalten Bibliotheken versteckte Methoden, die in einer mitgelieferten Header-Datei nicht enthalten sind, oder Sie möchten einfach die Syntax der Funktionen in der Header-Datei mit der Bibliothek vergleichen. Ich habe dazu einen Artikel auf codeproject.com gefunden, das Projekt funktionierte für mich allerdings nicht so gut, deshalb stelle ich hier meine C#-Implementierung zur Verfügung.

Mit dem hier vorgestellten Beispielcode können LIB Dateien erforscht werden und Funktionen in .h-Dateien exportiert werden - was für Visual C++-Entwickler nützlich sein könnte. Da das LIB-Format in seiner Ausprägung variiert, gibt es bezüglich dem universellen Einsatz einige Einschränkungen.

LIB-Datei mit ArchiveFileReader einlesen

Im Namespace MatthiasF.LibViewer.Core befindet sich die Klasse ArchiveFileReader, mit dem LIB-Dateien gelesen werden können. Folgender Schnipsel zeigt die Verwendung von ArchiveFileReader.

            static ArchiveFile LoadLibrary(
              string path)
            {
              FileInfo fi = new FileInfo(path)
              using (FileStream fs = fi.OpenRead())
              { using (ArchiveFileReader afr = new ArchiveFileReader(fs))
                { afr.UndecorateSymbols = true;
                  ArchiveFile af;
                  if ((af = afr.Read()) != null))
                    return af;

                }
              }
            }
          

Exportieren von Funktionen

Nachdem die Datei als ArchiveFile-Objekt geladen wurde, können die Funktionen einfach in eine .h-Datei exportiert werden.

            static void ExportSymbols(
              string libPath, 
              string hdrFilename)
            {
              ArchiveFile af;
              if ((af = LoadLibrary(libPath)) != null)
                af.ExportHeader(hdrFilename);
            
            }
          

Behind the scenes

Wenn man sich nach dem Laden der Linker-Member die Liste der Symbole anschaut, kann man feststellen, dass an einige Funktionsnamen seltsame Zeichenfolgen angehängt sind; diese sogenannten "Mangeled Names" werden vom C++-Compiler erzeugt und beinhalten Typ-Informationen.

In C++ wird das Überladen von Funktionen unterstützt, als das auch gleichnamige Funktionen in verschiedenen Klassen vorkommen können, sodass der Linker diese Informationen benötigt, um Aufrufe typsicher verbinden zu können. C-Compiler benötigen dies nicht, da ein Symbol nicht mehrfach existieren kann. In einer Header-Datei sind Funktionen undekoriert zu finden - vor dem Export der Symbole in eine .h-Datei müssen diese also wieder in lesbare Bezeichnungen konvertiert werden.

Mangeled Names auflösen

Unter Links finden Sie den Artikel "C++ Name Mangling/Demangling", der das Mangling/Demangling von Symbolen ausführlich beschreibt. Wer (wie ich) die Symbole nicht selbst wandeln möchte, kann das DBGHELP-API verwenden.


            [DllImport("dbghelp.dll", EntryPoint="UnDecorateSymbolName", CharSet=CharSet.Ansi)]
            static extern Int32 UnDecorateSymbolName(  
              [MarshalAs(UnmanagedType.LPStr)] string DecoratedName, 
              IntPtr UnDecoratedName,
              Int32 UndecoratedLength,
              Int32 Flags);
			

            static List<string> UndecorateSymbolsInternal(
              LinkerMember linkerMember)
            {
              List<string> undecorated = new List<string>();
              IDictionaryEnumerator ide;
              if ((ide = linkerMember.Symbols.GetEnumerator()) != null)
              { IntPtr p = Marshal.AllocHGlobal(4096);
                if (p.Equals(IntPtr.Zero) == false)
                { try
                  { while (ide.MoveNext())
                    { string symbolName = ( string ) ide.Value;
                      Int32 cch = 0;
                      if ((cch = UnDecorateSymbolName(symbolName, p, 4096, 0x0)) == 0)
                        undecorated.Add(symbolName); 
                        


                      else
                      { string undecoratedName = Marshal.PtrToStringAnsi(p, cch);            
                        undecorated.Add(undecoratedName);
                      }
                    }
                  }
                  finally { Marshal.FreeHGlobal(p); }
                }
              }
              
              return undecorated;
            }

          

Einschränkungen

Zunächst einmal hat es den Anschein, dass eine LIB in ihrem Format jeder anderen LIB gleich ist. Dies ist allerdings nicht der Fall, da jeder Compiler unterschiedliche LIB-Typen erzeugen und ein eigenes Name-Mangeling vornehmen kann, sodass der hier vorgestellte Code (Assembly-Projekt) keinesfalls universell einsetzbar ist. Ich habe das Werkzeug mit Hilfe der von Microsoft veröffentlichten PE/COFF-Spezifikation erstellt und mit beliebigen Bibliotheken getestet.

Funktionsparameter von C-Bibliotheken können (leider) nicht gewonnen werden.

Download

Ich stelle das Beispielprojekt hier für alle Interessierten zum Download zur Verfügung - erhebe allerdings keinen Anspruch auf Vollständigkeit der Implementierung, noch kann ich dafür garantieren, dass diese fehlerfrei ist. Viel Spass damit.

Kick it on dotnet-kicks.de

Links

Code-Project Artikel: "A tool to view a LIB"
http://www.codeproject.com/KB/debug/LibView.aspx
LIB-Viewer Projekt auf codeproject.com

Specification: Microsoft Portable Executable and Common Object File Format Specification
http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
This document specifies the structure of executable (image) files and object files under the Microsoft Windows family of operating systems.

Tutorial: C++ Name Mangling/Demangling
http://www.kegel.com/mangle.html
Website of Dan Kegel

Sample: Visual C# Beispielprojekt
Downloads/libcore.zip
Visual Studio 2005 Solution

Kommentar schreiben

Name*:  
Email*:  
Website:
Kommentar: