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)
{
var 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, int UndecoratedLength, int Flags);
static IEnumerable<string> UndecorateSymbolsInternal(LinkerMember linkerMember)
{
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)
yield return symbolName;
else
{
string undecoratedName = Marshal.PtrToStringAnsi(p, cch);
yield return undecoratedName;
}
}
}
finally { Marshal.FreeHGlobal(p); }
}
}
}
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.
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