Discussion:
[arch-general] Issue linking 32-bit GAS assembly
Dutch Ingraham
2018-10-17 19:36:37 UTC
Permalink
Hi all:

I'm having a problem linking 32-bit GAS assembly code that references external
C libraries on an up-to-date 64-bit Arch installation.

I have enabled the 32-bit repositories and installed the multilib-devel group
and lib32-glibc. I have updated the library cache with ldconfig and rebooted.

The command to assemble is: <as --32 -o filename.o filename.s>. Assembly
succeeds.

However, when linking using the command
<ld -melf_i386 --dynamic-linker /lib32/ld-linux.so.2 -lc -o filename filename.o>

the command fails with:
ld: skipping incompatible /usr/lib/libc.so when searching for -lc
ld: skipping incompatible /usr/lib/libc.a when searching for -lc
ld: cannot find -lc

Note this linker command (or a hierarchy-appropriate one) seems standard, and
succeeds on a 64-bit Debian OS.

There is a fairly recent Forum question (but pre-dating the discontinuance of
i686 support) regarding the same issue at
https://bbs.archlinux.org/viewtopic.php?id=229235 which indicates the command
should be:

<ld -melf_i386 -shared -L /usr/lib32 -dynamic-linker /lib/ld-linux.so.2 -o \
filename filename.o -lc>

This command succeeds, insofar as the linker returns an exit code of 0. However,
running the program (and all other similar programs) fails with "Illegal
instruction (core dumped)." Assembling with debugging symbols and running a
backtrace didn't enlighten me.

Note that changing /lib/ld-linux to /usr/lib32/ld-linux in the command immediately
above produces the same result, as confirmed by the output of <ldconfig -p>

Anyone see something I've missed of have any suggestions? Thanks.


-----------

Here is some simple code to test with:


# paramtest2.s - Listing system environment variables
.section .data
output:
.asciz "%s\n"
.section .text
.globl _start
_start:
movl %esp, %ebp
addl $12, %ebp
loop1:
cmpl $0, (%ebp)
je endit
pushl (%ebp)
pushl $output
call printf
addl $12, %esp
addl $4, %ebp
loop loop1
endit:
pushl $0
call exit
Maarten de Vries via arch-general
2018-10-17 21:07:02 UTC
Permalink
Why not let gcc take care of what compiler/assembler and linker to
invoke with which precise flags:

$ gcc -m32 -o foo filename.s
$ ./foo # great success!

It will probably link to libc without you even asking for it. And if
that works and you really want to know what linker flags you need, you
can add -v to make gcc spam you about it.


-- Maarten

(Sent off-list by accident before, sending to the list now.)
Post by Dutch Ingraham
I'm having a problem linking 32-bit GAS assembly code that references external
C libraries on an up-to-date 64-bit Arch installation.
I have enabled the 32-bit repositories and installed the multilib-devel group
and lib32-glibc. I have updated the library cache with ldconfig and rebooted.
The command to assemble is: <as --32 -o filename.o filename.s>. Assembly
succeeds.
However, when linking using the command
<ld -melf_i386 --dynamic-linker /lib32/ld-linux.so.2 -lc -o filename filename.o>
ld: skipping incompatible /usr/lib/libc.so when searching for -lc
ld: skipping incompatible /usr/lib/libc.a when searching for -lc
ld: cannot find -lc
Note this linker command (or a hierarchy-appropriate one) seems standard, and
succeeds on a 64-bit Debian OS.
There is a fairly recent Forum question (but pre-dating the discontinuance of
i686 support) regarding the same issue at
https://bbs.archlinux.org/viewtopic.php?id=229235 which indicates the command
<ld -melf_i386 -shared -L /usr/lib32 -dynamic-linker /lib/ld-linux.so.2 -o \
filename filename.o -lc>
This command succeeds, insofar as the linker returns an exit code of 0. However,
running the program (and all other similar programs) fails with "Illegal
instruction (core dumped)." Assembling with debugging symbols and running a
backtrace didn't enlighten me.
Note that changing /lib/ld-linux to /usr/lib32/ld-linux in the command immediately
above produces the same result, as confirmed by the output of <ldconfig -p>
Anyone see something I've missed of have any suggestions? Thanks.
-----------
# paramtest2.s - Listing system environment variables
.section .data
.asciz "%s\n"
.section .text
.globl _start
movl %esp, %ebp
addl $12, %ebp
cmpl $0, (%ebp)
je endit
pushl (%ebp)
pushl $output
call printf
addl $12, %esp
addl $4, %ebp
loop loop1
pushl $0
call exit
Dutch Ingraham
2018-10-17 22:01:46 UTC
Permalink
Why not let gcc take care of what compiler/assembler and linker to invoke
$ gcc -m32 -o foo filename.s
$ ./foo # great success!
It will probably link to libc without you even asking for it. And if that
works and you really want to know what linker flags you need, you can add -v
to make gcc spam you about it.
GCC will handle some files, but not others. In this case, I get
garbage output then a segfault/core dump.

Using -nostdlib and -static also fail to build, but I have had success
with just using <gcc -m32 -nostartfiles -o file file.s>

I would, however, like to know how to use as/ld on Arch, as it is my
main OS.
-- Maarten
(Sent off-list by accident before, sending to the list now.)
Post by Dutch Ingraham
I'm having a problem linking 32-bit GAS assembly code that references external
C libraries on an up-to-date 64-bit Arch installation.
I have enabled the 32-bit repositories and installed the multilib-devel group
and lib32-glibc. I have updated the library cache with ldconfig and rebooted.
The command to assemble is: <as --32 -o filename.o filename.s>. Assembly
succeeds.
However, when linking using the command
<ld -melf_i386 --dynamic-linker /lib32/ld-linux.so.2 -lc -o filename filename.o>
ld: skipping incompatible /usr/lib/libc.so when searching for -lc
ld: skipping incompatible /usr/lib/libc.a when searching for -lc
ld: cannot find -lc
Note this linker command (or a hierarchy-appropriate one) seems standard, and
succeeds on a 64-bit Debian OS.
There is a fairly recent Forum question (but pre-dating the discontinuance of
i686 support) regarding the same issue at
https://bbs.archlinux.org/viewtopic.php?id=229235 which indicates the command
<ld -melf_i386 -shared -L /usr/lib32 -dynamic-linker /lib/ld-linux.so.2 -o \
filename filename.o -lc>
This command succeeds, insofar as the linker returns an exit code of 0. However,
running the program (and all other similar programs) fails with "Illegal
instruction (core dumped)." Assembling with debugging symbols and running a
backtrace didn't enlighten me.
Note that changing /lib/ld-linux to /usr/lib32/ld-linux in the command immediately
above produces the same result, as confirmed by the output of <ldconfig -p>
Anyone see something I've missed of have any suggestions? Thanks.
-----------
# paramtest2.s - Listing system environment variables
.section .data
.asciz "%s\n"
.section .text
.globl _start
movl %esp, %ebp
addl $12, %ebp
cmpl $0, (%ebp)
je endit
pushl (%ebp)
pushl $output
call printf
addl $12, %esp
addl $4, %ebp
loop loop1
pushl $0
call exit
Dutch Ingraham
2018-10-17 21:51:11 UTC
Permalink
Post by Dutch Ingraham
I'm having a problem linking 32-bit GAS assembly code that references external
C libraries on an up-to-date 64-bit Arch installation.
I have enabled the 32-bit repositories and installed the multilib-devel group
and lib32-glibc. I have updated the library cache with ldconfig and rebooted.
The command to assemble is: <as --32 -o filename.o filename.s>. Assembly
succeeds.
However, when linking using the command
<ld -melf_i386 --dynamic-linker /lib32/ld-linux.so.2 -lc -o filename filename.o>
ld: skipping incompatible /usr/lib/libc.so when searching for -lc
ld: skipping incompatible /usr/lib/libc.a when searching for -lc
ld: cannot find -lc
Note this linker command (or a hierarchy-appropriate one) seems standard, and
succeeds on a 64-bit Debian OS.
There is a fairly recent Forum question (but pre-dating the discontinuance of
i686 support) regarding the same issue at
https://bbs.archlinux.org/viewtopic.php?id=229235 which indicates the command
<ld -melf_i386 -shared -L /usr/lib32 -dynamic-linker /lib/ld-linux.so.2 -o \
filename filename.o -lc>
This command succeeds, insofar as the linker returns an exit code of 0. However,
running the program (and all other similar programs) fails with "Illegal
instruction (core dumped)." Assembling with debugging symbols and running a
backtrace didn't enlighten me.
Note that changing /lib/ld-linux to /usr/lib32/ld-linux in the command immediately
above produces the same result, as confirmed by the output of <ldconfig -p>
Anyone see something I've missed of have any suggestions? Thanks.
-----------
# paramtest2.s - Listing system environment variables
.section .data
.asciz "%s\n"
.section .text
.globl _start
movl %esp, %ebp
addl $12, %ebp
cmpl $0, (%ebp)
je endit
pushl (%ebp)
pushl $output
call printf
addl $12, %esp
addl $4, %ebp
loop loop1
pushl $0
call exit
Silly question perhaps but does that file actually exist, /lib32/ld-linux.so.2?
I haven't set up 32 bit etc and that file doesn't exist on my machine,
and I get the exact same errors as you.
No, but /usr/lib32/ld-linux.so.2 does, as a symlink to ld-2.28.so. As
noted, I've tried that as well, with the same results.
Eli Schwartz via arch-general
2018-10-17 22:01:44 UTC
Permalink
Post by Dutch Ingraham
I'm having a problem linking 32-bit GAS assembly code that references external
C libraries on an up-to-date 64-bit Arch installation.
I have enabled the 32-bit repositories and installed the multilib-devel group
and lib32-glibc. I have updated the library cache with ldconfig and rebooted.
The command to assemble is: <as --32 -o filename.o filename.s>. Assembly
succeeds.
However, when linking using the command
<ld -melf_i386 --dynamic-linker /lib32/ld-linux.so.2 -lc -o filename filename.o>
ld: skipping incompatible /usr/lib/libc.so when searching for -lc
ld: skipping incompatible /usr/lib/libc.a when searching for -lc
ld: cannot find -lc
Note this linker command (or a hierarchy-appropriate one) seems standard, and
succeeds on a 64-bit Debian OS.
So, this is magical, why do you think it's supposed to work? Since Arch
isn't Debian, the first major issue is it violates the hierarchy... and
you didn't fix it, because there is no /lib32.

Second issue: the *error* it is showing is that it cannot find a
libc.so/libc.a, so the question you should be asking yourself is, what's
the search path? Apparently, the default search path on Debian works,
but here on Arch, /usr/lib32 is not in fact in the search path.

Fix those two problems and it compiles fine, and runs too.

But no.....
Post by Dutch Ingraham
There is a fairly recent Forum question (but pre-dating the discontinuance of
i686 support) regarding the same issue at
https://bbs.archlinux.org/viewtopic.php?id=229235 which indicates the command
<ld -melf_i386 -shared -L /usr/lib32 -dynamic-linker /lib/ld-linux.so.2 -o \
filename filename.o -lc>
This command succeeds, insofar as the linker returns an exit code of 0. However,
running the program (and all other similar programs) fails with "Illegal
instruction (core dumped)." Assembling with debugging symbols and running a
backtrace didn't enlighten me.
This fixes both problems, therefore it compiles cleanly. But it also
adds the "-shared" flag, which you have not asked yourself why you are
using it. Did you read the manpage for this?

-shared
Create a shared library. This is currently only supported on ELF,
XCOFF and SunOS platforms. On SunOS, the linker will automatically
create a shared library if the -e option is not used and there are
undefined symbols in the link.

...

Think, then do.
--
Eli Schwartz
Bug Wrangler and Trusted User
Anatol Pomozov via arch-general
2018-10-18 03:14:48 UTC
Permalink
Hello
Post by Dutch Ingraham
I'm having a problem linking 32-bit GAS assembly code that references external
C libraries on an up-to-date 64-bit Arch installation.
I have enabled the 32-bit repositories and installed the multilib-devel group
and lib32-glibc. I have updated the library cache with ldconfig and rebooted.
The command to assemble is: <as --32 -o filename.o filename.s>. Assembly
succeeds.
However, when linking using the command
<ld -melf_i386 --dynamic-linker /lib32/ld-linux.so.2 -lc -o filename filename.o>
ld: skipping incompatible /usr/lib/libc.so when searching for -lc
ld: skipping incompatible /usr/lib/libc.a when searching for -lc
ld: cannot find -lc
Note this linker command (or a hierarchy-appropriate one) seems standard, and
succeeds on a 64-bit Debian OS.
There is a fairly recent Forum question (but pre-dating the discontinuance of
i686 support) regarding the same issue at
https://bbs.archlinux.org/viewtopic.php?id=229235 which indicates the command
<ld -melf_i386 -shared -L /usr/lib32 -dynamic-linker /lib/ld-linux.so.2 -o \
filename filename.o -lc>
This command succeeds, insofar as the linker returns an exit code of 0. However,
running the program (and all other similar programs) fails with "Illegal
instruction (core dumped)." Assembling with debugging symbols and running a
backtrace didn't enlighten me.
Note that changing /lib/ld-linux to /usr/lib32/ld-linux in the command immediately
above produces the same result, as confirmed by the output of <ldconfig -p>
Anyone see something I've missed of have any suggestions? Thanks.
-----------
# paramtest2.s - Listing system environment variables
.section .data
.asciz "%s\n"
.section .text
.globl _start
movl %esp, %ebp
addl $12, %ebp
cmpl $0, (%ebp)
je endit
pushl (%ebp)
pushl $output
call printf
addl $12, %esp
addl $4, %ebp
loop loop1
pushl $0
call exit
Here is what I ran to make your example working on my Arch Linux machine


sudo pacman -S lib32-glibc
as --32 -o asm.o asm.s
ld -melf_i386 --dynamic-linker /lib/ld-linux.so.2 -L/usr/lib32 -lc -o asm asm.o
./asm


The only difference that I specified -L (library search path) to make
sure the linked can find 32-bit version of libc.
Dutch Ingraham
2018-10-18 14:09:35 UTC
Permalink
Post by Anatol Pomozov via arch-general
Hello
Post by Dutch Ingraham
I'm having a problem linking 32-bit GAS assembly code that references external
C libraries on an up-to-date 64-bit Arch installation.
I have enabled the 32-bit repositories and installed the multilib-devel group
and lib32-glibc. I have updated the library cache with ldconfig and rebooted.
The command to assemble is: <as --32 -o filename.o filename.s>. Assembly
succeeds.
However, when linking using the command
<ld -melf_i386 --dynamic-linker /lib32/ld-linux.so.2 -lc -o filename filename.o>
ld: skipping incompatible /usr/lib/libc.so when searching for -lc
ld: skipping incompatible /usr/lib/libc.a when searching for -lc
ld: cannot find -lc
Note this linker command (or a hierarchy-appropriate one) seems standard, and
succeeds on a 64-bit Debian OS.
There is a fairly recent Forum question (but pre-dating the discontinuance of
i686 support) regarding the same issue at
https://bbs.archlinux.org/viewtopic.php?id=229235 which indicates the command
<ld -melf_i386 -shared -L /usr/lib32 -dynamic-linker /lib/ld-linux.so.2 -o \
filename filename.o -lc>
This command succeeds, insofar as the linker returns an exit code of 0. However,
running the program (and all other similar programs) fails with "Illegal
instruction (core dumped)." Assembling with debugging symbols and running a
backtrace didn't enlighten me.
Note that changing /lib/ld-linux to /usr/lib32/ld-linux in the command immediately
above produces the same result, as confirmed by the output of <ldconfig -p>
Anyone see something I've missed of have any suggestions? Thanks.
-----------
# paramtest2.s - Listing system environment variables
.section .data
.asciz "%s\n"
.section .text
.globl _start
movl %esp, %ebp
addl $12, %ebp
cmpl $0, (%ebp)
je endit
pushl (%ebp)
pushl $output
call printf
addl $12, %esp
addl $4, %ebp
loop loop1
pushl $0
call exit
Here is what I ran to make your example working on my Arch Linux machine
sudo pacman -S lib32-glibc
as --32 -o asm.o asm.s
ld -melf_i386 --dynamic-linker /lib/ld-linux.so.2 -L/usr/lib32 -lc -o asm asm.o
./asm
The only difference that I specified -L (library search path) to make
sure the linked can find 32-bit version of libc.
Hi Anatol:

I was able assemble and link with gcc, then look at the library paths
used with ldd.

Actually, your command is the same as the command above, minus the
'shared' option, from the Forum post. That command was core dumping for
me; not sure how it was working for them.

Thanks for your help; your command works fine.

Loading...