Skip to content

feat(pe): add parse_imports option to ParseOptions#522

Open
supervacuus wants to merge 3 commits intom4b:masterfrom
supervacuus:feat/add_parse_imports_pe_option
Open

feat(pe): add parse_imports option to ParseOptions#522
supervacuus wants to merge 3 commits intom4b:masterfrom
supervacuus:feat/add_parse_imports_pe_option

Conversation

@supervacuus
Copy link
Copy Markdown

@supervacuus supervacuus commented Mar 27, 2026

Parsing PE import tables is expensive: for each DLL, the parser does a full pass over the import lookup table (resolving every symbol RVA via a linear scan over sections), a second pass over the import address table, and then a third reshaping pass in Import::parse. For binaries with large or malformed import tables, this adds up fast, especially when the caller only needs headers, debug info, or exports.

This PR adds a parse_imports flag to ParseOptions (default: true) with a with_parse_imports builder method, allowing callers to skip import table parsing entirely. When set to false, import_data, imports, and libraries remain empty while everything else is parsed as usual.

This is a follow-up to #506 (#508).

@supervacuus
Copy link
Copy Markdown
Author

Just wanted to ping if this kind of change is of interest.

I have also now added a new PR (#527) that fixes the underlying issue. It might still make sense to be able to turn off import parsing, but if #527 is accepted, I could understand if you didn't want to add another parser option. The resulting runtimes are now essentially the same for either PR.

@m4b
Copy link
Copy Markdown
Owner

m4b commented Apr 20, 2026

I'm ok with this i think, @kkent030315 is this something you think is fine?

Copy link
Copy Markdown
Contributor

@kkent030315 kkent030315 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

Comment thread src/pe/mod.rs Outdated
Comment on lines +197 to +198
if opts.parse_imports {
if let Some(&import_table) = optional_header.data_directories.get_import_table() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we merge it to one?

Suggested change
if opts.parse_imports {
if let Some(&import_table) = optional_header.data_directories.get_import_table() {
if opts.parse_imports && let Some(&import_table) = optional_header.data_directories.get_import_table()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rust is pinned at 1.85 in CI which complains about the let chain.

Otherwise fixed in: 9f632ae

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use

if let (true, Some(&import_table)) = (                                                                                                                              
    opts.parse_imports,                                                                                                                                             
    optional_header.data_directories.get_import_table(),                                                                                                            
) {                                                                                                                                                                 

}

if you prefer it to if-nesting. However, that means get_import_table() will be called unconditionally (which is not a costly invocation, but a change in behavior nonetheless).

Changed here: db951f2

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.

3 participants