Calling DLL functions involves the linker generating a stub, unless the function was declared __declspec(dllimport) in which case the stub can be bypassed in favor of an indirect call straight to the import table which is slightly more efficient, e.g.
__declspec(dllimport) void ExitProcess(int);
ExitProcess(0);
generates
call qword ptr [__imp_ExitProcess]
where __imp_ExitProcess resolves to a location in the import table in the executable.
I'm trying to figure out exactly how __imp_ExitProcess is resolved. It occurs as a symbol in kernel32.lib to be sure, but that symbol has storage class IMAGE_SYM_CLASS_EXTERNAL, section number zero and value zero, which amounts to just saying 'this will be defined somewhere else' without actually ever defining it.
Does the __imp_ prefix have special meaning, i.e. does the linker notice that prefix and take it as an instruction to resolve the symbol to the import table entry for the DLL function whose name has that prefix removed? Or is something else going on?
The linker adds to your program a function like:
void (*__imp_ExitProcess)(int) = ...;
void ExitProcess(int n)
{
return (*__imp_ExitProcess)(n);
}
where __imp_ExitProcess points to the "real" ExitProcess in KERNEL32.DLL.
Declaring this in your code:
__declspec(dllimport) void ExitProcess(int);
is equivalent to:
extern void (*__imp_ExitProcess)(int);
#define ExitProcess (*__imp_ExitProcess)
except that __declspec(dllimport) is handled by the compiler, not by the preprocessor.
Just came up with a test that gives a data point. The following program:
__declspec(dllimport) void ExitProcess(int);
void __imp_ExitProcess(int x) {
}
int main() {
ExitProcess(0);
}
crashes when compiled with the Microsoft compiler and run (but runs okay if the empty function is renamed to anything else); thus, it seems the linker behaves as though the __imp_ name is special, at least in the sense that a linker that behaves that way will generate a correct executable in all cases where the Microsoft linker does so, unless I'm missing something.
Members of kernel32.lib are not normal object files but special placeholders. From the PE/COFF spec:
Traditional import libraries, that is, libraries that describe the
exports from one image for use by another, typically follow the layout
described in section 7, “Archive (Library) File Format.” The primary
difference is that import library members contain pseudo-object files
instead of real ones, in which each member includes the section
contributions that are required to build the import tables that are
described in section 6.4, “The .idata Section.” The linker generates
this archive while building the exporting application.
The section contributions for an import can be inferred from a small set of information. The linker can either generate the complete,
verbose information into the import library for each member at the
time of the library’s creation or write only the canonical information
to the library and let the application that later uses it generate the
necessary data on the fly.
[...] a short import library is written as follows:
Archive member header
Import header
Null-terminated import name string
Null-terminated DLL name string
This is sufficient information to accurately reconstruct the entire contents of the member at the time of its use.
In kernel32.lib on my machine, __imp_ExitProcess is mentioned in the first and second linker members (symbol list) and point to the specific pseudo-object describing the import:
Archive member name at 8: /
50107C36 time/date Thu Jul 26 01:07:34 2012
uid
gid
0 mode
106CA size
correct header end
2515 public symbols
[...]
3C874 ExitProcess
3C874 __imp_ExitProcess
[...]
Archive member name at 3C874: KERNEL32.dll/
50107639 time/date Thu Jul 26 00:42:01 2012
uid
gid
0 mode
2D size
correct header end
Version : 0
Machine : 8664 (x64)
TimeDateStamp: 50107639 Thu Jul 26 00:42:01 2012
SizeOfData : 00000019
DLL name : KERNEL32.dll
Symbol name : ExitProcess
Type : code
Name type : name
Hint : 371
Name : ExitProcess
So, as you can see, the data in .lib explicitly says that it refers to an import name ExitProcess from the DLL KERNEL32.dll. The linker can use this to build necessary metadata in the import section.
Now, the above only discussed how the __imp_ExitProcess symbol is resolved. I'm not 100% sure but I think if a symbol (e.g. ExitProcess) has been resolved to such an import stub, and it does not start with __imp_, then the linker has to generate a jump stub (for code symbols), or an indirect access (for data accesses) to the IAT slot.
Related
So I'm trying to compile this project : https://github.com/dmitrystu/libusb_stm32 with Segger Embedded studio which uses gcc. The process is choking on this error :
pasting formed 'u"Open source USB stack for STM32"', an invalid preprocessing token
which is caused by this line :
static const struct usb_string_descriptor manuf_desc_en = USB_STRING_DESC("Open source USB stack for STM32");
So USB_STRING_DESC is a macro :
#define USB_STRING_DESC(s) {.bLength = sizeof(CAT(u,s)),.bDescriptorType = USB_DTYPE_STRING,.wString = {CAT(u,s)}}
And CAT is a macro CAT(x,y) x##y. The intent must be to convert a string of type 8-bit char into a 16-bit Unicode type but the compiler doesn't like it. Is there some #include or compiler setting that may be missing that I have to add here? Clearly the author of this code expects it to work so there must be some fault in my setup.
Also I'm not clear on how the sizeof() operation is supposed to work here. As I understand it there is no way to get the length of a string at compile time so that operation will always return the size of a pointer.
In response to Keith's question, the gcc version is 4.2.1. Poking around the compiler settings the default option is the C99 standard, when I changed it to C11 everything compiled just fine. Thanks!
Related to but not equivalent to DLL Get Symbols From Its Parent (Loader)
Is there a way to convince the Windows loader to resolve a particular symbol referenced by A.dll from either the loading executable or an intermediate dll without specifying the file to resolve symbols from in A.dll?
It's pretty obvious how to do it if the loading .exe has a known name, but if it isn't ...
Here's a good reason why you'd actually want to do this: https://www.gnu.org/software/libc/manual/html_node/Replacing-malloc.html
If this can be done, a good answer would say how to do it some way or another.
I'm half-expecting the answer is it can't be done. In that case, a good answer would show why this is impossible. "The build tools don't support this." is a bad answer.
when we use import we need exactly indicate module name and function name. and we can not use complex algorithms. also for exe not exist well known alias which we can use in place exactly exe name. for compare: in case get GetModuleHandle we can use NULL for get handle to the file used to create the calling process (.exe file). but in case LoadLibraryExW we can not use 0 or empty string (L"") or some another alias for say - we want handle to exe. when loader load our module - he read dll name from IMAGE_IMPORT_DESCRIPTOR and try found or load module with this name first by low level, private, core of LoadLibraryExW. here need exactly name. or load fail. as result use import - not a solution here, if we dont know exe name at build time
possible variant - resolve functions pointers yourself at runtime. here we can get exe HMODULE by GetModuleHandle(0). also if need we can search function not only in exe but somewhere else. can implement any search algorithm.
here exist several ways. for concrete example let we need get pointer to function with signature:
void WINAPI fn(int i);
we can declare pointer to this function and resolve it in runtime
void (WINAPI *fn)(int);
*(void**)&fn = GetProcAddress(GetModuleHandleW(0), "fn");
say on DLL_PROCESS_ATTACH
a slightly different solution (although at the binary level it is completely equivalent) declare function with __declspec(dllimport) attribute. this is for CL.EXE (more known as MSVC) compiler only. so
__declspec(dllimport) void fn(int i);
in this case CL yourself generate pointer to function with name __imp_ ## __FUNCDNAME__ name. so by fact the same as in first variant, when we declare pointer yourself. only difference in syntax and.. symbol name. it will be look like __imp_?fn2##YAXH#Z. problem here that __imp_?fn2##YAXH#Z not valid name for c/c++ - we can not direct assign value to it from c/c++. even if we declare function with extern "C" - function name will be containing # symbol (illegal for c++) for __stdcall and __fastcall functions, for x86. also name will be different for different platforms (x86, x64, etc). for access such names - need or use external asm file (for asm ? and # symbols valid in name) or use /alternatename linker option - for set alias for such name and access symbol via it. say like
__pragma(comment(linker, "/alternatename:__imp_?fn##YAXH#Z=__imp_fn"))
and init via
*(void**)&__imp_fn = GetProcAddress(GetModuleHandle(0), "fn");
another option use __declspec(dllimport) in function declarations + add import library, where all __imp___FUNCDNAME__ (such __imp_?fn2##YAXH#Z) is defined. (even if we have not such library we can easy create it yourself - all what need - correct function declarations with empty implementation). and after we add such import lib to linker input - add /DELAYLOAD:dllname where dllname - exactly name from import lib. sense that this dllname will(can) be not match to exe - all what need - it must be unique. and we need yourself handle delayload (called when we first time call fn). for implement delayload we need implement
extern "C" FARPROC WINAPI __delayLoadHelper2(
PCImgDelayDescr pidd,
FARPROC * ppfnIATEntry
);
we can implement it yourself, or add delayimp.lib to our project. here (in delayimp.lib) the delayLoadHelper2 and implemented. however we must customize this process (default implementation(look in /include/DelayHlp.cpp) will be use LoadLibraryExA with dllname which is not excepted in our case - otherwise we can be simply use import as is). so we need mandatory implement __pfnDliNotifyHook2:
for example:
FARPROC WINAPI MyDliHook(
unsigned dliNotify,
PDelayLoadInfo pdli
)
{
switch (dliNotify)
{
case dliNotePreLoadLibrary:
if (!strcmp(pdli->szDll, "unique_exe_alias"))
{
return (FARPROC)GetModuleHandle(0);
}
}
return 0;
}
const PfnDliHook __pfnDliNotifyHook2 = MyDliHook;
we can look for dliNotePreLoadLibrary notification and instead default LoadLibraryEx(dli.szDll, NULL, 0); use GetModuleHandle(0); for get base of exe.
the "unique_exe_alias" (which linker got from import library) here play role not real exe name, which is unknown, but unique tag(alias) for exe
I'm trying to make COSMIC compiler allocate a struct at a specific address in the memory (0x5420). I added the following lines in my C code (where CAN_TypeDef is a typedef struct):
#pragma section [mycan]
CAN_TypeDef CAN;
#pragma section []
In the IDE (STVD), I created a new section named Can inside which I created a new section named .mycan.
When I build the code in STVD, a linker error appears saying:
#error clnk Debug\can.lkf:1 bad address (0x5420) for zero page symbol _CAN
In the above picture, it is clear that Can and Zero Page are two different segments. What can be the cause of this error and how can I solve it?
I don't know the STM8, but I think I found it. In the STVD documentation I read:
Global variables
When the category is set to General , you can use
the Global Variables list box to specify the default location of
global variables:
In Zero Page: This is the default option.
In Data: Specifies to place global variables in the first 64Kbytes of
memory.
So the compiler assumes all global data sitting in the zero page and the addresses are just eight bit wide. Only the linker sees that the section .mycan is not in the zero page and you get an error. I would try #near CAN_TypeDef CAN; or simply extern CAN_TypeDef CAN #5420; without creating your own section.
My application has a number of modules that each require some variables to be stored in off-chip non-volatile memory. To make the reading and writing of these easier, I'm trying to collect them together into a contiguous region of RAM, to that the NVM driver can address a single block of memory when communicating with the NVM device.
To achieve this, I have created a custom linker script containing the following section definition.
.nvm_fram :
{
/* Include the "nvm_header" input section first. */
*(.nvm_header)
/* Include all other input sections prefixed with "nvm_" from all modules. */
*(.nvm_*)
/* Allocate a 16 bit variable at the end of the section to hold the CRC. */
. = ALIGN(2);
_gld_NvmFramCrc = .;
LONG(0);
} > data
_GLD_NVM_FRAM_SIZE = SIZEOF(.nvm_fram);
The data region is defined in the MEMORY section using the standard definition provided by Microchip for the target device.
data (a!xr) : ORIGIN = 0x1000, LENGTH = 0xD000
One example of a C source file which attempts to place its variables in this section is the NVM driver itself. The driver saves a short header structure at teh beginning of the NVM section so that it can verify the content of the NVM device before loading it into RAM. No linker error reported for this variable.
// Locate the NVM configuration in the non-volatile RAM section.
nvm_header_t _nvmHeader __attribute__((section(".nvm_header")));
Another module that has variables to store in the .nvm_fram section is the communications (CANopen) stack. This saves the Module ID and bitrate in NVM.
// Locate LSS Slave configuration in the non-volatile RAM section.
LSS_slave_config_t _slaveConfig __attribute__((section(".nvm_canopen"))) =
{ .BitRate = DEFAULT_BITRATE, .ModuleId = DEFAULT_MODULEID };
Everything compiles nicely, but when the linker runs, the following error stops the build.
elf-ld.exe: Link Error: attributes for input section '.nvm_canopen' conflict with
output section '.nvm_fram'
It's important that the variables can be initialised with values by the crt startup, as shown by the _slaveConfig declaration above, in case the NVM driver cannot load them from the NVM device (it's blank, or the software version has changed, etc.). Is this what's causing the attributes mismatch?
There are several questions here and on the Microchip forums, which relate to accessing symbols that are defined in the linker script from C. Most of these concern values in the program Flash memory and how to access them from C; I know how to do this. There is a similar question, but this doesn't appear to address the attributes issue, and is a little confusing due to being specific to a linker for a different target processor.
I've read the Microchip linker manual and various GCC linker documents online, but can't find the relevant sections because I don't really understand what the error means and how it relates to my code. What are the 'input and output section attributes', where are they specified in my code, and how do I get them to match eachother?
The problem is due to the _nvmHeader variable not having an initial value assigned to it in the C source, but the _slaveConfig variable does.
This results in the linker deducing that the .nvm_fram output section is uninitialised (nbss) from the .nvm_header input section attributes. So, when it enconters initialised data in the .nvm_canopen input section from the _slaveConfig variable, there is a mismatch in the input section attributes: .nvm_fram is for uninitialised data, but .nvm_canopen contains initialised data.
The solution is to ensure that all variables that are to be placed in the .nvm_fram output section are given initial values in the C source.
// Type used to hold metadata for the content of the NVM.
typedef struct
{
void* NvmBase; // The original RAM address.
uint16_t NvmSize; // The original NVM section size.
} nvm_header_t;
// The linker supplies the gld_NVM_FRAM_SIZE symbol as a 'number'.
// This is represented as the address of an array of unspecified
// length, so that it cannot be implicitly dereferenced, and cast
// to the correct type when used.
extern char GLD_NVM_FRAM_SIZE[];
// The following defines are used to convert linker symbols into values that
// can be used to initialise the _nvmHeader structure below.
#define NVM_FRAM_BASE ((void*)&_nvmHeader)
#define NVM_FRAM_SIZE ((uint16_t)GLD_NVM_FRAM_SIZE)
// Locate the NVM configuration in the non-volatile RAM section.
nvm_header_t _nvmHeader __attribute__((section(".nvm_header"))) =
{
.NvmBase = NVM_FRAM_BASE, .NvmSize = NVM_FRAM_SIZE
};
The answer is therefore that the output section attributes may be determined partly by the memory region in which the section is to be located and also by the attributes of the first input section assigned to it. Initialised and uninitialised C variables have different input section attributes, and therefore cannot be located within the same output section.
On Linux, when linking I can specify any virtual address for a section:
ld -Ttext 0x10000000 -Tdata 0x20000000 foo.o -o foo
But I don't see such option for Windows' link.exe.
Is it possible to specify PE section start addresses somehow?
MinGW ld can put the sections at arbitrary addresses. Dumpbin and disassemblers can handle it without problem.
But it seems Windows does not accept anything but the default address: if you try to set it to a different value Windows will say "not a valid Win32 application".
The base address must be 0x400000 or 0x1000000.
And the .text section must be at 0x401000 or 0x1001000.
Also it seems no gaps allowed between the sections. If I try to place the .data section to 0x403000 instead of 0x402000, then Windows is unable to load it...
(I maybe wrong, or mingw ld is buggy...)
When using GCC, this page explains how to define variables at absolute addresses (including mentioning the section in which they should reside) : https://mcuoneclipse.com/2012/11/01/defining-variables-at-absolute-addresses-with-gcc/
The idea I use here is to put the variable with a special section
name, and then place it in the linker file at an absolute address.
unsigned char __attribute__((section (".myBufSection"))) buf[128]
__attribute__ ((aligned (512)));
With this, my variable will be put into a section named
‘.myBufSection’, and it will be aligned on a 512 address boundary.
The next step is to place that section at an address in the linker file.
SECTIONS
{
/* placing my named section at given address: */
.myBufBlock 0x20000000 :
{
KEEP(*(.myBufSection)) /* keep my variable even if not referenced */
} > m_data
/* other placements follow here... */
}
PS: Another method is mentioned in How can I declare a variable at an absolute address with GCC?
PS 2: Another related (alas unanswered) question is this : How to place a variable at a given absolute address in memory (with Visual C++)