Skip to content

Fix IDA 9.0–9.2 build: emulate bookmarks_t::get_by_inode() (#35)#36

Merged
0xeb merged 1 commit into
mainfrom
fix/bookmarks-get-by-inode-pre93
Jun 23, 2026
Merged

Fix IDA 9.0–9.2 build: emulate bookmarks_t::get_by_inode() (#35)#36
0xeb merged 1 commit into
mainfrom
fix/bookmarks-get-by-inode-pre93

Conversation

@0xeb

@0xeb 0xeb commented Jun 23, 2026

Copy link
Copy Markdown
Member

Fixes #35.

Problem

bookmarks_t::get_by_inode() was introduced in IDA 9.3. The bookmark collectors referenced it directly, so building against the 9.0/9.1/9.2 SDKs failed at both compile (no such member) and link (no exported bookmarks_t_get_by_inode).

Fix

Route both call sites (symbols_bookmarks.cpp, types_bookmarks.cpp) through a new idasql_bookmarks_get_by_inode() wrapper in ida_compat.hpp, gated by IDASQL_HAS_BOOKMARKS_GET_BY_INODE (IDA_SDK_VERSION >= 930):

  • 9.3+ → forwards to the real bookmarks_t::get_by_inode() (no behavior change).
  • pre-9.3 → emulates with the stable size() / get() store API.

How the emulation works

The standard bookmark dirtrees key each leaf inode by the place's primary coordinate. Verified empirically on 9.3:

  • idaplace (EA) bookmarks: inode == ea — the dirtree leaf is even named after the hex EA (e.g. /mine/100000558).
  • tiplace (local-type) bookmarks: mirror this by ordinal (and don't get a leaf from mark() by default, so this path is dormant).

Both collectors only ever pass real dirtree-leaf inodes (enumerated via collect_inode_paths), so the shim scans the store and returns the slot whose coordinate matches the inode, leaving out_entry/out_desc populated by get() exactly as get_by_inode would. is_place_class_ea_capable() selects the coordinate without constructing a place (idalib doesn't export tiplace_t's constructor — we only read members off places get() fills).

Verification

  • Compiles + links against SDK 9.0, 9.1, 9.2, 9.3 (9.0/9.1/9.2 previously failed at get_by_inode).
  • Functional parity: forcing the emulation path on the working 9.3 runtime returns byte-for-byte identical bookmarks and local_type_bookmarks rows (slot / inode / address / description / folder_path / full_path) vs. the real get_by_inode.

No CMake changes; header-only addition plus two one-line call-site swaps.

bookmarks_t::get_by_inode() was added in IDA 9.3; building the bookmark
collectors against the 9.0/9.1/9.2 SDKs failed at both compile (no such
member) and link (no exported bookmarks_t_get_by_inode).

Route both call sites through a new idasql_bookmarks_get_by_inode()
wrapper in ida_compat.hpp, gated by IDASQL_HAS_BOOKMARKS_GET_BY_INODE
(IDA_SDK_VERSION >= 930). On 9.3+ it forwards to the real API; on older
SDKs it emulates with the stable size()/get() store API.

The standard bookmark dirtrees key each leaf inode by the place's primary
coordinate (verified on 9.3: idaplace inode == ea, the leaf is even named
after the hex ea; tiplace mirrors by ordinal). Both collectors only pass
real leaf inodes, so the emulation scans the store and returns the slot
whose coordinate matches, leaving out_entry/out_desc filled by get()
exactly as get_by_inode would. is_place_class_ea_capable() selects the
coordinate without constructing a place (idalib does not export tiplace's
constructor).

Verified: compiles + links against SDK 9.0/9.1/9.2/9.3; forcing the
emulation path on the 9.3 runtime returns byte-for-byte identical
bookmarks / local_type_bookmarks rows vs the real get_by_inode.
@0xeb
0xeb merged commit 7e1a644 into main Jun 23, 2026
2 of 8 checks passed
@0xeb
0xeb deleted the fix/bookmarks-get-by-inode-pre93 branch June 23, 2026 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IDA 9.1 compatibility: missing bookmarks_t::get_by_inode() API

1 participant