2

I'm trying to determine - using IdaPython - if a function prototype is user-defined or have been automatically guessed / defined by IDA (i.e. without specific user interaction).

The flag is probably available somewhere but I haven't been able to find it, despite multiple tries.

According to the documentation for the Functions Window:

A bold font is used for functions that have a definite (user-specified) prototype.

For example (disassembled Windows kernel with PDB), in the Functions window the PsReferenceImpersonationToken function is in bold, and its decompiled code prototype (signature) is in blue:

User-defined function

On the other hand, the ObReferenceFileObjectForWrite function is not in bold in the Functions window, and its decompiled function prototype is in yellow:

Non user-defined function

What I'd like to find - using IdaPython - is that, given a function ea: is the function prototype user-defined or not? (i.e. bold in functions windows and blue in the decompiler).

I've tried using cfunc_t and cfuncptr_t, checking the flags between various functions, but nothing definitive came out of it. Tried also with the vds4.py example (with some modifications) but to no avail.

Note: I'm using IDA Pro 9.0 SP1 and have the x64 decompiler.

1 Answer 1

2

In the SDK, there are some altflags that can be used to distinguish whether a prototype for a given address has been guessed or specified by the user.

Specifically, you'd use the get_aflags function to get the 32-bit "aflags" for the address. After getting the flags, you'd then mask out your desired bit fields. The bitmask to select who guessed the prototype is AFL_TYPE_GUESSED(0xC2000000).

After you select the bits related to the AFL_TYPE_GUESSED field, you can then compare your result against one of the AFL_*_GUESSED flags, or specifically the AFL_USERTI flag to distinguish whether the prototype was determined explicitly by the user, ida, or the decompiler. The available additional flags are documented here.

If you're using IDAPython, you'll also probably want to use idaapi.as_uint32 to ensure you get an unsigned value since the AFL_TYPE_GUESSED bitmask has its high bit set.

So, the IDAPython code might look like:

def is_user_defined(ea): res = idaapi.get_aflags(ea) unsigned = idaapi.as_uint32(res) who = unsigned & idaapi.AFL_TYPE_GUESSED return who == idaapi.AFL_USERTI 

It's probably worth noting that the "aflags" are stored in a netnode as an altval at the index NALT_AFLAGS(8) for the target address. If not using set_aflags, you can also use this to modify them.


Disclaimer: I'm the maintainer of the ida-minsc plugin that you can find on github at https://github.com/arizvisa/ida-minsc.

If you're using the ida-minsc plugin, the type information, names, and comments for all the things are indexed into the database and can be searched with tags. The specific tag name for the type information being manually applied to an address (or identifier for a structure or its members) is "__typeinfo__" and can be queried with database.select. Similarly, if you're trying to differentiate structures you created from ones automatically imported, you can use structure.select.

for ea, tags in database.select('__typeinfo__'): if function.has(ea): print(hex(ea), function.name(ea), function.type(ea), function.tag(ea)) continue 

You can also use matchers (via the database.functions namespace) to select only the functions that are tagged, or you can gather them into a list if you want to filter them some more.

database.functions.list(tagged='__typeinfo__', like='sub_*') results = database.functions(tagged='__typeinfo__', decompiled=False) database.functions.list(ea=results, tagged=['__name__', 'synopsis'], problems=True) 

To select functions that have not been prototyped by the user, you can do some basic set-arithemtic on the addresses returned. You can also use the "predicate" matcher with a custom test that selects functions not contained within the set.

tagged_results = set(database.functions(tagged='__typeinfo__', like='sub_*')) database.functions.list(address=set(database.functions()) - tagged_results) database.functions.list(predicate=lambda ea: ea not in results) 

Disclaimer: Currently (as of 2025-05-08) the minsc plugin is limited to v8.4 due to the removal of the structure/enumeration api in 8.5 and 9.x.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.