Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read short import files #555

Merged
merged 2 commits into from
Jun 26, 2023
Merged

Read short import files #555

merged 2 commits into from
Jun 26, 2023

Conversation

ChrisDenton
Copy link
Contributor

@ChrisDenton ChrisDenton commented Jun 16, 2023

See #512.

This adds some support for reading short import library files. These only appear in archives and are Windows specific. Unlike most other content of .lib archives, these are not object files. Instead they are a header that minimal describes how the linker should update the .idata section (aka DLL import tables) for a specific symbol. This header is followed by two strings: the DLL name and the public symbol name. Note that according to a comment in src/pe.rs there can also be a third string, though I can't find this documented anywhere. In any case supporting it isn't difficult.

I've added support to the objdump example to show how it could be used.

Posting this as a draft PR for feedback and just in case I don't have time to finish, someone else can pick it up. I still need to add some tests. It'd also be nice to have at least some minimal write support.

src/read/import.rs Outdated Show resolved Hide resolved
src/read/coff/import.rs Show resolved Hide resolved
src/read/coff/import.rs Outdated Show resolved Hide resolved
src/read/coff/import.rs Outdated Show resolved Hide resolved
src/read/coff/import.rs Outdated Show resolved Hide resolved
src/read/coff/import.rs Outdated Show resolved Hide resolved
src/read/mod.rs Outdated Show resolved Hide resolved
src/read/mod.rs Outdated Show resolved Hide resolved
@ChrisDenton
Copy link
Contributor Author

One issue with testing in CI is that I've not yet figured out how to produce lib files with different name types using standard tools. I can test using lib files on my machine but committing them may be legally dubious (I am not a lawyer).

src/read/coff/import.rs Outdated Show resolved Hide resolved
@philipc
Copy link
Contributor

philipc commented Jun 17, 2023

One issue with testing in CI is that I've not yet figured out how to produce lib files with different name types using standard tools. I can test using lib files on my machine but committing them may be legally dubious (I am not a lawyer).

That's one of the reasons for putting the test files in a separate repository, although I would prefer to be able to generate them using standard tools if we can. What are the standard tools for this? I could look into it too.

@ChrisDenton
Copy link
Contributor Author

In MSVC land, you can pass a .def file to lib.exe to create an import lib. E.g. lib /DEF:example_dll.def /MACHINE:X64. Or when building a DLL there's the dllexport attributes used in C/C++ to annotate functions or data. And there's the /EXPORT linker argument. Any DLL exports should generate an import lib file when compiled.

LLVM has equivalents. E.g. llvm-dlltool or llvm-lib which, like lib.exe, can convert a def file to an import lib. Or lld-link for the linker.

@philipc
Copy link
Contributor

philipc commented Jun 19, 2023

Thanks for the info. I also found that you can use cl example_dll.cpp /LD /link /DEF:example_dll.def. Compiling for both x86 and x64, and using with and without extern "C" allows all the IMPORT_OBJECT_* variants to be generated except for IMPORT_OBJECT_NAME_EXPORTAS. I couldn't find any way to generate that, since it always generates an export that is the same as the undecorated name, even when using aliases.

LLVM doesn't have any support for IMPORT_OBJECT_NAME_EXPORTAS (it also never parses the DLL name either), so I don't mind if we don't have a test for it. Also of interest is that LLVM calls this a COFFImportFile.

src/read/mod.rs Outdated Show resolved Hide resolved
@ChrisDenton
Copy link
Contributor Author

Ah, I figured out how to build with different name types. It depends on the architecture. x86 (aka i386) uses NoPrefix and arm64ex uses ExportAs. The "arm64ex" architecture isn't supported by LLVM tho. Here's my def file:

LIBRARY test
EXPORTS

; code
foo
bar @1
baz @2 NONAME

; data
FOO DATA
BAR CONSTANT ; warning LNK4087: CONSTANT keyword is obsolete; use DATA
BAZ @3 DATA
QUX @4 NONAME DATA

If you'll pardon my powershell, here's what I'm using to generate libs:

MSVC

foreach ($arch in 'arm','arm64','arm64ec','arm64x','x64','x86') { lib /def:test.def /machine:$arch /out:import_msvc_$arch.lib /NOLOGO  }

LLVM

foreach ($arch in 'arm','arm64','i386','i386:x86-64') { llvm-dlltool -d test.def -l import_llvm_$($arch -replace 'i386:', '').lib -m $arch }

tests/read/coff.rs Outdated Show resolved Hide resolved
@ChrisDenton ChrisDenton marked this pull request as ready for review June 24, 2023 13:23
Copy link
Contributor

@philipc philipc left a comment

Choose a reason for hiding this comment

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

Thanks!

@philipc philipc merged commit bcbf98b into gimli-rs:master Jun 26, 2023
12 checks passed
@ChrisDenton ChrisDenton deleted the imports branch June 28, 2023 09:02
poliorcetics pushed a commit to JustRustThings/object that referenced this pull request Jul 24, 2023
mcbegamerxx954 pushed a commit to mcbegamerxx954/object that referenced this pull request Jun 15, 2024
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.

None yet

3 participants