Handling of Exports slightly off
Closed this issue · 4 comments
From the comments:
// We want to use NumberOfFunctions
for looping as it's the total number of functions/symbols
// exported by the module. On the other hand, NumberOfNames
is the number of
// functions/symbols exported by name only.
exports->functions_count = exp->NumberOfFunctions;
const size_t functions_size = exp->NumberOfFunctions * sizeof(pe_exported_function_t);
exports->functions = malloc(functions_size);
if (exports->functions == NULL) {
exports->err = LIBPE_E_ALLOCATION_FAILURE;
return exports;
}
memset(exports->functions, 0, functions_size);
for (uint32_t i=0; i < exp->NumberOfFunctions; i++) {
This is slightly wrong. NumberOfNames can differ from NumberOfFunctions, either smaller or larger. You really have three things to deal with:
NumberOfFunctions - All Symbols exported
NumberOfNames - All names that match up to symbols
Function exported by ordinal only
For this last one, you need to take all functions, and subtract out the ones that got names. The ones that are left are the ones exported by ordinal only.
Also, the 'ordinal' is actually a 'hint', which is the actual offset into the first array, meaning it is zero based. Any usage of ordinals is purely on the input side, meaning, if a user calls get pointer and uses an ordinal, the ordinal base is subtracted to give you the 0-index. The named things don't actually do this calculation, they just use the offset directly (counter to MS documentation).
Hi @Wiladams! Thanks for the report.
I'm not sure if I fully understand your point. You mean the comment is slightly off, or the implementation, or both?
NumberOfNames can differ from NumberOfFunctions, either smaller or larger.
- you mean that NumberOfNames
can be larger than NumberOfFunctions
?
My understanding is that NumberOfFunctions
is the total number of exported functions, therefore NumberOfNames
should never be larger than NumberOfFunctions
. Both will have the same value if all functions are exported by name.
You could have a number of names bigger than NumberOfFunctions, if the names are aliases to functions. I can have 'funcA' and 'funcB' both point to index '3', or whatever. This might happen as a .dll ages, and you want to maintain old names while introducing new ones, pointing to the same actual code.
You can definitely have a case where NumberOfNames is less than NumberOfFunctions. In this case, you might have some exports that are only available through ordinal only (no associated name). To find those, refer to my comment.
I would suggest looking through a bunch of .dll files on Windows in the \Windows\System32 directory. You'll find all manner of edge cases, and things that don't match your expectations from the documentation.
Interesting. Will take a look. Thanks for sharing!