最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - What is the condition for symbol equality for a linker on Windows? - Stack Overflow

programmeradmin4浏览0评论

I'm writing a linker for Windows. I compiled a simple "hello world" program using cl.exe, and now I'm trying to link it using my custom linker, but it's not working. It works fine using link.exe.

// hello.c
#include <stdio.h>

int main(void) {
    printf("Hello, Windows!\n");
    return 0;
}

The generated object file contains an undefined symbol called ?_OptionsStorage@?1??__local_stdio_printf_options@@9@9.

# dumpbin output
00F 00000000 SECT4  notype ()    External     | ___local_stdio_printf_options
010 00000000 UNDEF  notype ()    External     | ___acrt_iob_func
011 00000000 UNDEF  notype ()    External     | ___stdio_common_vfprintf
012 00000000 SECT5  notype ()    External     | __vfprintf_l
013 00000000 SECT6  notype ()    External     | _printf
014 00000000 SECT3  notype ()    External     | _main
015 00000008 UNDEF  notype       External     | ?_OptionsStorage@?1??__local_stdio_printf_options@@9@9 (`__local_stdio_printf_options'::`2'::_OptionsStorage)
016 00000000 SECT7  notype       Static       | .data
    Section length   11, #relocs    0, #linenums    0, checksum F2A3A4F3
018 00000000 SECT7  notype       Static       | $SG9585
019 00000000 SECT8  notype       Static       | .chks64
    Section length   40, #relocs    0, #linenums    0, checksum        0

My linker is unable to resolve this symbol, because it compares symbols using simple string comparison. libcmt.lib does contain a similar symbol called ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA in one of its object files:

# dumpbin output
07A 00000000 SECT27 notype       Static       | .xdata$x
    Section length   1C, #relocs    2, #linenums    0, checksum 6A27921E, selection    5 (pick associative Section 0x1C)
07C 00000000 SECT27 notype       Static       | __sehtable$?notify_debugger@@YAXABUtagEXCEPTION_VISUALCPP_DEBUG_INFO@@@Z
07D 00000000 SECT28 notype       Static       | .bss
    Section length    8, #relocs    0, #linenums    0, checksum        0, selection    2 (pick any)
07F 00000000 SECT28 notype       External     | ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA (unsigned __int64 `__local_stdio_printf_options'::`2'::_OptionsStorage)
080 00000000 SECT29 notype       Static       | .rdata
    Section length   6C, #relocs    0, #linenums    0, checksum DD6D9A7E, selection    2 (pick any)
082 00000000 SECT29 notype       External     | ??_C@_1GM@CNOOJIHC@?$AAR?$AAu?$AAn?$AAt?$AAi?$AAm?$AAe?$AA?5?$AAC?$AAh?$AAe?$AAc?$AAk?$AA?5?$AAE@ (`string')
083 00000000 SECT2A notype       Static       | .rdata

These symbols look very similar. When I use undname.exe to unmangle them, it looks like the former ends up being a suffix of the latter:

Undecoration of :- "?_OptionsStorage@?1??__local_stdio_printf_options@@9@9"
is :- "`__local_stdio_printf_options'::`2'::_OptionsStorage"

Undecoration of :- "?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA"
is :- "unsigned __int64 `__local_stdio_printf_options'::`2'::_OptionsStorage"

But this isn't enough to answer my questions, which are:

  • How do I figure out whether ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA is the symbol that link.exe is using to successfully resolve the undefined symbol in hello.obj? Running link.exe with /VERBOSE and/or /MAP doesn't seem to give me this information.
  • If this is the definition that is selected for symbol resolution, why? The symbol names are not exactly the same.
  • Is there a different check besides simple equality that I should be doing in my linker to make this work properly? How do I do this robustly?

I'm writing a linker for Windows. I compiled a simple "hello world" program using cl.exe, and now I'm trying to link it using my custom linker, but it's not working. It works fine using link.exe.

// hello.c
#include <stdio.h>

int main(void) {
    printf("Hello, Windows!\n");
    return 0;
}

The generated object file contains an undefined symbol called ?_OptionsStorage@?1??__local_stdio_printf_options@@9@9.

# dumpbin output
00F 00000000 SECT4  notype ()    External     | ___local_stdio_printf_options
010 00000000 UNDEF  notype ()    External     | ___acrt_iob_func
011 00000000 UNDEF  notype ()    External     | ___stdio_common_vfprintf
012 00000000 SECT5  notype ()    External     | __vfprintf_l
013 00000000 SECT6  notype ()    External     | _printf
014 00000000 SECT3  notype ()    External     | _main
015 00000008 UNDEF  notype       External     | ?_OptionsStorage@?1??__local_stdio_printf_options@@9@9 (`__local_stdio_printf_options'::`2'::_OptionsStorage)
016 00000000 SECT7  notype       Static       | .data
    Section length   11, #relocs    0, #linenums    0, checksum F2A3A4F3
018 00000000 SECT7  notype       Static       | $SG9585
019 00000000 SECT8  notype       Static       | .chks64
    Section length   40, #relocs    0, #linenums    0, checksum        0

My linker is unable to resolve this symbol, because it compares symbols using simple string comparison. libcmt.lib does contain a similar symbol called ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA in one of its object files:

# dumpbin output
07A 00000000 SECT27 notype       Static       | .xdata$x
    Section length   1C, #relocs    2, #linenums    0, checksum 6A27921E, selection    5 (pick associative Section 0x1C)
07C 00000000 SECT27 notype       Static       | __sehtable$?notify_debugger@@YAXABUtagEXCEPTION_VISUALCPP_DEBUG_INFO@@@Z
07D 00000000 SECT28 notype       Static       | .bss
    Section length    8, #relocs    0, #linenums    0, checksum        0, selection    2 (pick any)
07F 00000000 SECT28 notype       External     | ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA (unsigned __int64 `__local_stdio_printf_options'::`2'::_OptionsStorage)
080 00000000 SECT29 notype       Static       | .rdata
    Section length   6C, #relocs    0, #linenums    0, checksum DD6D9A7E, selection    2 (pick any)
082 00000000 SECT29 notype       External     | ??_C@_1GM@CNOOJIHC@?$AAR?$AAu?$AAn?$AAt?$AAi?$AAm?$AAe?$AA?5?$AAC?$AAh?$AAe?$AAc?$AAk?$AA?5?$AAE@ (`string')
083 00000000 SECT2A notype       Static       | .rdata

These symbols look very similar. When I use undname.exe to unmangle them, it looks like the former ends up being a suffix of the latter:

Undecoration of :- "?_OptionsStorage@?1??__local_stdio_printf_options@@9@9"
is :- "`__local_stdio_printf_options'::`2'::_OptionsStorage"

Undecoration of :- "?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA"
is :- "unsigned __int64 `__local_stdio_printf_options'::`2'::_OptionsStorage"

But this isn't enough to answer my questions, which are:

  • How do I figure out whether ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA is the symbol that link.exe is using to successfully resolve the undefined symbol in hello.obj? Running link.exe with /VERBOSE and/or /MAP doesn't seem to give me this information.
  • If this is the definition that is selected for symbol resolution, why? The symbol names are not exactly the same.
  • Is there a different check besides simple equality that I should be doing in my linker to make this work properly? How do I do this robustly?
Share Improve this question edited 4 hours ago Pepijn Kramer 12.9k3 gold badges11 silver badges25 bronze badges asked 4 hours ago laptoulaptou 7,0213 gold badges33 silver badges67 bronze badges 2
  • This question reveals one weakness of that archaic technology based on object files and name-bases linking used by C++ and other languages. The way to overcome the difficulties like that was developed long time ago and is based on well-structured metadata: Ada, Pascal variant from Turbo Pascal to Delphi to Free Pascal, entire .NET, and more. That brings me to the question: what is the purpose of creation of a new linker? I really would like to know. – Sergey A Kryukov Commented 3 hours ago
  • libucrt.lib containing ?_OptionsStorage@?1??__local_stdio_printf_options@@9@9 symbol. in what problem ? question is trivial – RbMm Commented 3 hours ago
Add a comment  | 

1 Answer 1

Reset to default 0

link.exe always uses exact name matches only. ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA is not used of course. used exactly ?_OptionsStorage@?1??__local_stdio_printf_options@@9@9 and this symbol exist in libucrt.lib as example. maybe in some another libs too

How do I figure out whether ?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA is the symbol that link.exe is using to successfully resolve the undefined symbol in hello.obj?

?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA not used

Is there a different check besides simple equality that I should be doing in my linker to make this work properly? How do I do this robustly?

no

发布评论

评论列表(0)

  1. 暂无评论