Last active
October 4, 2021 04:15
-
-
Save alberthdev/ae013060a5d51b754e43d46fb16cba8f to your computer and use it in GitHub Desktop.
010 editor template - AR .a, .lib, .ar, .deb with Microsoft / Visual Studio (MSVC) specific parsing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//------------------------------------------------ | |
//--- 010 Editor v11.0 Binary Template | |
// | |
// File: AR.bt | |
// Authors: SweetScape Software + Albert Huang (GitHub @alberthdev) | |
// Version: 1.1 | |
// Purpose: Parse ar archives used for .a, .lib, | |
// .ar and .deb files. | |
// Category: Archive | |
// File Mask: *.a,*.lib,*.ar,*.deb | |
// ID Bytes: 21 3C 61 72 63 68 3E 0A //!<arch>\n | |
// History: | |
// 1.1 2021-10-05 Albert Huang: Support for MSVC specific structures + LUTs. | |
// 1.0 2020-10-23 SweetScape Software: Initial version. | |
//------------------------------------------------ | |
// MSFT shenanigans | |
local int isMsft = 0; | |
typedef struct { | |
char name[]; | |
} nullTermString <read=ReadNullTermString>; | |
string ReadNullTermString( struct nullTermString &f ) | |
{ | |
return f.name; | |
} | |
typedef struct { | |
BigEndian(); | |
ulong numSymbols; | |
ulong symOffsets[numSymbols]; | |
LittleEndian(); | |
nullTermString symbols[numSymbols] <optimize=false>; | |
} ar_msft_first_archive_linker_member; | |
typedef struct { | |
ulong numMembers; | |
ulong memberOffsets[numMembers]; | |
ulong numSymbols; | |
short symOffsets[numSymbols]; | |
nullTermString publicSymbols[numSymbols] <optimize=false>; | |
} ar_msft_second_archive_linker_member; | |
local int readingSecond = 0; | |
local int64 longNamesOffset = 0; | |
local int64 longNamesSize = 0; | |
local int64 longNameReqIdx = 0; | |
string getLongNameByIdx(int64 idx) { | |
local int64 curIdx = 0; | |
local int64 parsedSize = longNamesSize; | |
local string longName = ReadString(longNamesOffset + (longNamesSize - parsedSize)); | |
while ((parsedSize > 0) && (curIdx <= idx)) { | |
longName = ReadString(longNamesOffset + (longNamesSize - parsedSize)); | |
parsedSize -= (Strlen(longName) + 1); | |
curIdx++; | |
} | |
return longName; | |
} | |
// File record | |
typedef struct { | |
// Define header | |
SetBackColor( cLtYellow ); | |
char fileName[16]; | |
char modification_timestamp[12]; | |
char ownerID[6]; | |
char groupID[6]; | |
char fileMode[8]; | |
char fileSize[10]; | |
char endMarker[2]; | |
SetBackColor( cNone ); | |
// Define file data | |
if( endMarker == "\x60\x0a" ) | |
{ | |
local int64 size; | |
SScanf( fileSize, "%Ld", size ); | |
if ((fileName == "/ ") && (size > 0)) { | |
isMsft = 1; | |
if (readingSecond == 0) { | |
ar_msft_first_archive_linker_member member; | |
readingSecond = 1; | |
} else { | |
ar_msft_second_archive_linker_member member; | |
} | |
} else if ((fileName == "// ") && (size > 0)) { | |
local int64 parsedSize = size; | |
local int64 numLongNames = 0; | |
local string longName = ""; | |
longNamesSize = size; | |
longNamesOffset = FTell(); | |
while (parsedSize > 0) { | |
longName = ReadString(longNamesOffset + (size - parsedSize)); | |
parsedSize -= (Strlen(longName) + 1); | |
numLongNames++; | |
} | |
if( size & 1 ) numLongNames--; | |
nullTermString longNames[numLongNames] <optimize=false>; | |
} else { | |
local int matchLongNameReqd = RegExMatch(fileName, "/\\d+\\s+"); | |
if ((matchLongNameReqd == 1) && (size > 0)) { | |
local int64 usinglongNameIdx = longNameReqIdx; | |
longNameReqIdx++; | |
local string realFilename = getLongNameByIdx(usinglongNameIdx); | |
} | |
if( size > 0 ) | |
uchar data[size]; | |
} | |
// Add padding byte | |
if( size & 1 ) | |
uchar padding <bgcolor=cLtGray>; | |
} | |
} ar_file <read=ReadArFile>; | |
// Display filename beside ar_file struct | |
string ReadArFile( struct ar_file &f ) | |
{ | |
if (isMsft) { | |
if (f.fileName == "/ ") { | |
return "MSFT Archive Linker Member"; | |
} else if (f.fileName == "// ") { | |
return "MSFT Long Names"; | |
} else if (exists(f.matchLongNameReqd) && (f.matchLongNameReqd == 1)) { | |
return f.realFilename + " size=" + f.fileSize + " (using long name; real name: " + f.fileName + ")"; | |
} else { | |
// trim trailing slash | |
local string fileNameWithoutSlash = ""; | |
Strcpy(fileNameWithoutSlash, f.fileName); | |
fileNameWithoutSlash = StrDel(fileNameWithoutSlash, Strchr(fileNameWithoutSlash, '/'), 1); | |
return fileNameWithoutSlash + " ns size=" + f.fileSize; | |
} | |
} | |
return f.fileName + " size=" + f.fileSize; | |
} | |
// Read the file signature | |
char signature[8] <bgcolor=cLtPurple>; | |
if( signature != "!<arch>\n" ) | |
{ | |
Warning( "File is not a valid archive. Template stopped." ); | |
return -1; | |
} | |
// Read file records | |
while( !FEof() ) | |
{ | |
ar_file file; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment