Shi, Steven via llvm-dev
2019-Feb-18 08:53 UTC
[llvm-dev] lld-link fails to link 32bits assembly functions but 64bits pass
Hi Martin, Thank you for the hint.> For 32 bit windows, functions with cdecl calling convention (the default > in C) are decorated with an underscore prefix. So you'd need to update > your nasm source file to define the symbol _Foo instead of Foo. (Most > assembly files use some sort of macro for wrapping this detail.)Yes, my assembly files do use prefix macro (ASM_PFX) for wrapping the underscore. We use the __USER_LABEL_PREFIX__ to control the prefix macro expand to be "_" as below. I find the __USER_LABEL_PREFIX__ has been predefined by clang-cl, but it is defined as nothing. That is why my prefix macro expands to be nothing. Do you know why the clang-cl predefines the __USER_LABEL_PREFIX__ as nothing? #ifndef __USER_LABEL_PREFIX__ #define __USER_LABEL_PREFIX__ _ #endif #define _CONCATENATE(a, b) __CONCATENATE(a, b) #define __CONCATENATE(a, b) a ## b #define ASM_PFX(name) _CONCATENATE (__USER_LABEL_PREFIX__, name) Thanks Steven> -----Original Message----- > From: Martin Storsjö [mailto:martin at martin.st] > Sent: Monday, February 18, 2019 3:29 PM > To: Shi, Steven <steven.shi at intel.com> > Cc: Rui Ueyama <ruiu at google.com>; 'Peter Smith' > <peter.smith at linaro.org>; 'llvm-dev at lists.llvm.org' <llvm-dev at lists.llvm.org> > Subject: Re: [llvm-dev] lld-link fails to link 32bits assembly functions but > 64bits pass > > On Mon, 18 Feb 2019, Shi, Steven via llvm-dev wrote: > > > > > Hi Rui, Peter, > > > > You know I’m enabling the “clang-cl + lld-link” toolchain for Uefi firmware. > > I meet a problem that the lld-link fails to link 32bits assembly functions, > > but can link 64bits assembly functions successfully. I need your suggestion. > > > > Below is an example to show my problem in linux. The example has two > only > > source files: main.c and foo.nasm. > > > > > > > > $ cat main.c > > > > void Foo (void); > > > > int main() > > > > { > > > > Foo(); > > > > return 0; > > > > } > > > > > > > > $ cat foo.nasm > > > > SECTION .text > > > > global Foo > > > > Foo: > > > > Ret > > > > > > > > 64bits compiling and linking is successful: > > > > $ nasm foo.nasm -Ox -f win64 -g -o foo.obj > > > > $ ~/llvm/releaseinstall/bin/clang-cl main.c /nologo /c /WX /GS- /W4 > /Gs32768 > > /D UNICODE /O1b2s /EHs-c- /GR- /GF /Gy /Zi /Gw -m64 > > > > $ ~/llvm/releaseinstall/bin/lld-link main.obj foo.obj /NOLOGO > /NODEFAULTLIB > > /IGNORE:4001 /OPT:REF /OPT:ICF=10 /ALIGN:32 /SECTION:.xdata,D > > /SECTION:.pdata,D /DLL /ENTRY:main > /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER > > /SAFESEH:NO /BASE:0 /DRIVER: /DEBUG:GHASH /Machine:X64 > > > > > > > > But 32bits linking fails with error of Foo assembly function is a undefined > > symbol: > > > > $ nasm foo.nasm -Ox -f win32 -g -o foo.obj > > > > $ ~/llvm/releaseinstall/bin/clang-cl main.c /nologo /c /WX /GS- /W4 > /Gs32768 > > /D UNICODE /O1b2 /EHs-c- /GR- /GF /Gy /Zi /Gw -m32 > > > > $ ~/llvm/releaseinstall/bin/lld-link main.obj foo.obj /NOLOGO > /NODEFAULTLIB > > /IGNORE:4001 /OPT:REF /OPT:ICF=10 /ALIGN:32 /SECTION:.xdata,D > > /SECTION:.pdata,D /DLL /ENTRY:main > /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER > > /SAFESEH:NO /BASE:0 /DRIVER: /DEBUG:GHASH /MACHINE:X86 > > > > lld-link: error: undefined symbol: _Foo > > > > >>> referenced by /home/jshi19/llvm/wrongcode/lld-link/main.c:4 > > > > >>> main.obj:(_main) > > For 32 bit windows, functions with cdecl calling convention (the default > in C) are decorated with an underscore prefix. So you'd need to update > your nasm source file to define the symbol _Foo instead of Foo. (Most > assembly files use some sort of macro for wrapping this detail.) > > > > BTW, I find the lld-link does not suppor the /MAP option to generate > > mapfile. If I hope to output the linking mapfile info, what option should I > > use? > > lld-link has got a private option /lldmap:<filename> which does output > some sort of filename. I'm not sure what the reasons are for providing it > under a private name instead of supporting the link.exe option /map. Maybe > the format of the generated mapfile differs so that it might not work for > automatic tools that operate on the map file at least. > > // Martin
Martin Storsjö via llvm-dev
2019-Feb-18 09:07 UTC
[llvm-dev] lld-link fails to link 32bits assembly functions but 64bits pass
On Mon, 18 Feb 2019, Shi, Steven wrote:> Hi Martin, > Thank you for the hint. > >> For 32 bit windows, functions with cdecl calling convention (the default >> in C) are decorated with an underscore prefix. So you'd need to update >> your nasm source file to define the symbol _Foo instead of Foo. (Most >> assembly files use some sort of macro for wrapping this detail.) > Yes, my assembly files do use prefix macro (ASM_PFX) for wrapping the > underscore. We use the __USER_LABEL_PREFIX__ to control the prefix macro > expand to be "_" as below. I find the __USER_LABEL_PREFIX__ has been > predefined by clang-cl, but it is defined as nothing. That is why my > prefix macro expands to be nothing. Do you know why the clang-cl > predefines the __USER_LABEL_PREFIX__ as nothing?It looks to me like __USER_LABEL_PREFIX__ is properly defined to an underscore when preprocessing with clang-cl: $ cat userprefix.c __USER_LABEL_PREFIX__ $ bin/clang-cl -E userprefix.c -m32 # 1 "userprefix.c" # 1 "<built-in>" 1 # 1 "<built-in>" 3 # 331 "<built-in>" 3 # 1 "<command line>" 1 # 1 "<built-in>" 2 # 1 "userprefix.c" 2 _ $ bin/clang-cl -E userprefix.c # 1 "userprefix.c" # 1 "<built-in>" 1 # 1 "<built-in>" 3 # 334 "<built-in>" 3 # 1 "<command line>" 1 # 1 "<built-in>" 2 # 1 "userprefix.c" 2 $ So as long as I specify a x86 32 bit target, __USER_LABEL_PREFIX__ expands correctly to an underscore. Where do you observe differing behaviour? If you use (clang-)cl to preprocess your assembler files, you need make sure you run that preprocessor with the right target. // Martin
Shi, Steven via llvm-dev
2019-Feb-18 14:54 UTC
[llvm-dev] lld-link fails to link 32bits assembly functions but 64bits pass
Hi Martin, OK, It was my fault. I didn't set correct target when run the preprocess. Thank you very much! Thanks Steven> -----Original Message----- > From: Martin Storsjö [mailto:martin at martin.st] > Sent: Monday, February 18, 2019 5:07 PM > To: Shi, Steven <steven.shi at intel.com> > Cc: Rui Ueyama <ruiu at google.com>; 'Peter Smith' > <peter.smith at linaro.org>; 'llvm-dev at lists.llvm.org' <llvm- > dev at lists.llvm.org>; Gao, Liming <liming.gao at intel.com> > Subject: RE: [llvm-dev] lld-link fails to link 32bits assembly functions but > 64bits pass > > On Mon, 18 Feb 2019, Shi, Steven wrote: > > > Hi Martin, > > Thank you for the hint. > > > >> For 32 bit windows, functions with cdecl calling convention (the default > >> in C) are decorated with an underscore prefix. So you'd need to update > >> your nasm source file to define the symbol _Foo instead of Foo. (Most > >> assembly files use some sort of macro for wrapping this detail.) > > Yes, my assembly files do use prefix macro (ASM_PFX) for wrapping the > > underscore. We use the __USER_LABEL_PREFIX__ to control the prefix > macro > > expand to be "_" as below. I find the __USER_LABEL_PREFIX__ has been > > predefined by clang-cl, but it is defined as nothing. That is why my > > prefix macro expands to be nothing. Do you know why the clang-cl > > predefines the __USER_LABEL_PREFIX__ as nothing? > > It looks to me like __USER_LABEL_PREFIX__ is properly defined to an > underscore when preprocessing with clang-cl: > > $ cat userprefix.c > __USER_LABEL_PREFIX__ > $ bin/clang-cl -E userprefix.c -m32 > # 1 "userprefix.c" > # 1 "<built-in>" 1 > # 1 "<built-in>" 3 > # 331 "<built-in>" 3 > # 1 "<command line>" 1 > # 1 "<built-in>" 2 > # 1 "userprefix.c" 2 > _ > $ bin/clang-cl -E userprefix.c > # 1 "userprefix.c" > # 1 "<built-in>" 1 > # 1 "<built-in>" 3 > # 334 "<built-in>" 3 > # 1 "<command line>" 1 > # 1 "<built-in>" 2 > # 1 "userprefix.c" 2 > > $ > > So as long as I specify a x86 32 bit target, __USER_LABEL_PREFIX__ expands > correctly to an underscore. Where do you observe differing behaviour? If > you use (clang-)cl to preprocess your assembler files, you need make sure > you run that preprocessor with the right target. > > // Martin