Idatil2c
Convert IDA Type Library `*.til` to Compilable C Header!
Install / Use
/learn @NyaMisty/Idatil2cREADME
idatil2c
Convert IDA Type Library *.til to Compilable C Header!
Related Project
This repo is intended to be used in other projects, enabling various C parser to directly use IDA's type library
- ida_kern_til: Convert IDA libs to Python ctypes
- ghidra_ida_til: Convert IDA til to Ghidra GDT
- ghidra_objc: Export ObjC class parsed by IDA to Ghidra
How to Use
- Install Node.JS (For faster RegExp) and PyPy (for faster, but CPython is also OK)
- Export TIL content using
tilib -lc XXX.til > XXX.til.h - Run script:
- Simplest:
python3 idatil2c.py input/XXX.til.h output/XXX.til.h - With dependency:
python3 idatil2c.py input/XXX.til.h output/XXX.til.h depends1.h depends2.h ...- The script will exclude defined types, and convert to #include statements, so there won't duplicate types.
- Simplest:
- Throw them to others:
- Ghidra: Compile to GDT
- CtypesLib: Convert to Ctypes Wrapper
How it works?
BeforeAll: Everything in this script is based on RegEx, so it's highly dependent on tilib's stable output fomat
-
Sanitize Header: (see
sanitizeHdr) Remove ALL C++ things- Remove various Cpp syntax:
::?~ - Replace template arguments
<XXX>using regex - Remove VFT
- Remove definition that's same as depends header
- That's round1, there'll still be forward decls to be removed
- Remove various Cpp syntax:
-
Parse Each Line: (see
parseDecls) This step does not do filtering- Get each definition line's type class (typedef/union/enum/struct/etc.), type name
- Removes various modifiers, so that RegEx would be easier
'__cdecl', '__cppobj', '__unaligned', 'volatile', '__declspec\([^()]+\)', '__declspec\([^()]+\([^()]+\)\)', # mssdk '__far', # bc5w16: IOleInPlaceActiveObject far *This '__attribute__(XXX)', - Remove comments
-
Filter Decls: (see
filterDecls)- Remove blacklist types
- Remove depends definition (round2)
- Check if types are defined in depends:
^(struct|union|enum)( [\w\d_]+)*%s [{:] - Only defs like
struct XXX {orstruct XXX : YYY {are accepted
- Check if types are defined in depends:
-
PostProcess Decls: (see
processDecls)- Handle anonymous nested structs (usually union types)
- Example: struct XXX {union {char A; int B;};};
- We need to extract the union to corresponding type (usually XXX::$ABCDEF12345)
- For Clang:
- Convert
enumtoenum class: because clang doesn't likeenum XXX : int32 {, but it likesenum class XXX : int32 {
- Convert
- For Ghidra:
- Ghidra simply can't specify enum's base type, we have to replace both
enum class XXX : YYYandenum XXX : YYYtoenum XXX - Ghidra does not support multi class inherit: we have to convert
struct XXX: YYY, ZZZintostruct XXX { YYY __cppsuper0; ZZZ __cppsuper1; };
- Ghidra simply can't specify enum's base type, we have to replace both
- Handle anonymous nested structs (usually union types)
-
Calculate Type Dependencies and Output: (see
outputCtypesLibCpp)- Ignore pure forward declarations (IDA's TIL ensures that a type name can only appear once, so there won't be forward decl and complete decl at same time)
- Compare each type to each type one by one
- Even if it's only a O(n^2) operation, that would be too slow using Python
- Instead, we fill all typenames into one RegEx, and uses JS to search it, then it would be a O(nlogn) operation
- RegEx:
(?<=[ ;*(){},\[])(${Object.keys(typeDefs).join('|')})([ ;*(){},\[]+)
- Check chars after typename to see whether it's pointer ref or direct ref, and check if it can be ignored
- For struct/union they can be forward declarations, so pointer ref can be ignored.
- If we are typedef, then typedef to struct/union can also be ignored.
- Replace builtin type's definition (like
typedef XXX wchar_t) to#define - BFS iterate all dependency pairs, and generate final output in the order of dependency
-
Final Output:
- Replace various invalid identifiers: (Used in struct/union fields)
constfloatregisterdefault- (For Ghidra):
_extension (...)->(int, ...)
- Ghidra does not support array in method parameters (like
int XXX(char *arg1[]))- Case1:
TYPNAME (*)FieldName[] - Case2:
TYPNAME (*)[] - Case3:
int (*methName[])(XXXXX) - Actually TYPNAME can have modifiers like
unsigned
- Case1:
- Generate include statements
- Generate macro statements (for TYPEDEF_HELPERS)
- Replace various invalid identifiers: (Used in struct/union fields)
Related Skills
node-connect
343.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
90.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
343.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
343.1kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
