$ cat dlleg.c __attribute((__dllexport__)) void fn () { } __attribute((__dllexport__)) char hello[] = "Hello world"; __attribute((__dllexport__)) int init_data = 42; __attribute((__dllexport__)) int uninit_data; $ cat dlleg2.c __attribute((__dllexport__)) void fn2 () { } __attribute((__dllexport__)) char hello2[] = "Hello again"; __attribute((__dllexport__)) int init_data2 = 44; __attribute((__dllexport__)) int uninit_data2; $ cat dllegmain.c __attribute((__dllimport__)) void fn (); __attribute((__dllimport__)) char hello[]; __attribute((__dllimport__)) int init_data; __attribute((__dllimport__)) int uninit_data; __attribute((__dllimport__)) void fn2 (); __attribute((__dllimport__)) char hello2[]; __attribute((__dllimport__)) int init_data2; __attribute((__dllimport__)) int uninit_data2; int main () { fn(); uninit_data = init_data; fn2(); uninit_data2 = init_data2; return 0; } $ gcc -g -c dlleg.c $ gcc -g -c dlleg2.c $ gcc -g -c dllegmain.c $ # $ # Note - by omitting the --enable-auto-image-base linker flag, both $ # DLLs get the same load address by default (0x1000000). At load $ # time, one of them gets relocated $ # $ gcc -shared -o dlleg.dll dlleg.o $ gcc -shared -o dlleg2.dll dlleg2.o $ gcc -o dllegmain dllegmain.o dlleg.dll dlleg2.dll $ gdb dllegmain GNU gdb 5.2.1 Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "mingw32"... (gdb) break main Breakpoint 1 at 0x401050: file dllegmain.c, line 13. (gdb) run Starting program: f:\Users\Raoul\gdb/dllegmain.exe Breakpoint 1, main () at dllegmain.c:13 13 fn(); (gdb) x/s &hello 0x10002000 : "Hello again" (gdb) # (gdb) # Uh oh. The symbol "hello" should point to the string (gdb) # "Hello world", and hello2 should be "Hello again" (gdb) # (see dlleg.c and dlleg2.c above) (gdb) # (gdb) x/s &hello2 0x10002000 : "Hello again" (gdb) # (gdb) # win32-nat.c knows the real load addresses: (gdb) # (gdb) info dll DLL Name Load Address F:\cygwin\bin\cygwin1.dll 61001000 F:\WINNT\system32\kernel32.dll 77e81000 f:\Users\Raoul\gdb\dlleg2.dll 10001000 f:\Users\Raoul\gdb\dlleg.dll 00331000 F:\WINNT\system32\advapi32.dll 77db1000 F:\WINNT\system32\rpcrt4.dll 77d41000 F:\WINNT\system32\user32.dll 77e11000 F:\WINNT\system32\gdi32.dll 77f41000 (gdb) # (gdb) # Using this information, we can find the other string (gdb) # manually. dlleg2.dll got loaded at it's preferred (gdb) # address, but dlleg.dll was relocated. (gdb) # (gdb) x/s 0x332000 0x332000: "Hello world" (gdb) quit The program is running. Exit anyway? (y or n) y $