undefined reference to `__imp___gmpz_init', building GMP program on Cygwin - gcc

I'm trying to compile this simple GMP program on Cygwin:
#include <gmp.h>
int main(){
mpz_t i;
mpz_init(i);
}
This is the command:
gcc -lgmp test.c
I get this error:
/tmp/ccJpGa7K.o:test.c:(.text+0x17): undefined reference to `__imp___gmpz_init'
/tmp/ccJpGa7K.o:test.c:(.text+0x17): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `__imp___gmpz_init'
collect2: error: ld returned 1 exit status
Any idea what's wrong? I know it can find the library (libgmp.dll.a), but it doesn't seem to find the function.
Output of nm /usr/lib/libgmp.dll.a | grep mpz_init:
0000000000000000 T __gmpz_inits
0000000000000000 I __imp___gmpz_inits
0000000000000000 T __gmpz_init_set_ui
0000000000000000 I __imp___gmpz_init_set_ui
0000000000000000 T __gmpz_init_set_str
0000000000000000 I __imp___gmpz_init_set_str
0000000000000000 T __gmpz_init_set_si
0000000000000000 I __imp___gmpz_init_set_si
0000000000000000 T __gmpz_init_set_d
0000000000000000 I __imp___gmpz_init_set_d
0000000000000000 T __gmpz_init_set
0000000000000000 I __imp___gmpz_init_set
0000000000000000 T __gmpz_init2
0000000000000000 I __imp___gmpz_init2
0000000000000000 T __gmpz_init
0000000000000000 I __imp___gmpz_init
I tried it without grep and every single symbol in there has address 0 for some reason.

This fixed it: gcc test.c -lgmp. I just put -lgmp last. This seems to be something particular to Cygwin, I tried it with both Clang and gcc-4.9 on OS X and they don't care about the order.
As for the strange behavior with the dll.a file, this is because some *.a files are just stubs that cause linking against the actual cyg*.dll which are all in /usr/bin or /usr/local/bin. However, I think this should always be automatic because Cygwin tries to be POSIX, so if you do it right then you shouldn't have to reference cyg*.dll files.
Found out from here:
https://cygwin.com/ml/cygwin/2011-12/msg00305.html

Using g++ main.c -o main -lgmp worked for me.
Basically, all I had to do was putting the -lgmp in the end.

I also had the same issue while using gmp.h with codeblocks on Windows 7. My solution
1. Install gmp from deval while installing cygwin
2. Add path the path of libgmp.a and libgmp.dll.a in your editor's linker
3. Rebuild all.

Related

i386 x86_64 architecture Assembly language no symbol error

just started out assembly programming, after compiling it with nasm and when i open the file with gdb ./myfile, (No debugging symbols found in ./sandbox (its my file name))
tried many commands from terminal objdump, nm and all, no debugging symbol found in ./sandbox
ASM code
section .data
section .text
global _start
_start:
nop
; put your experiments between here
; put your experiments between here
nop
section .bss
Code from makefile
sandbox: sandbox.o
ld -m elf_i386 -s -o sandbox sandbox.o
sandbox.o: sandbox.asm
nasm -f elf -g -F dwarf sandbox.asm -l sanbox.lst
error getting from gdb objdump
(No debugging symbols found in ./sandbox (its my file name))

nasm - Can't link object file with ld on macOS Mojave

I'm trying to assemble a simple Hello World, which worked fine in the previous macOS version:
global start
section .text
start: mov rax, 0x02000004
mov rdi, 1
mov rsi, msg
mov rdx, 13
syscall
mov rax, 0x02000001
xor rdi, rdi
syscall
section .data
msg: db "Hello world!", 10
Then I use nasm and ld as I did before:
$ nasm -f macho64 hello.asm
$ ld hello.o -o hello
But ld gives me the following error:
ld: warning: No version-min specified on command line
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for inferred architecture x86_64
I tried switching start to _main, but got the following:
ld: warning: No version-min specified on command line
ld: dynamic main executables must link with libSystem.dylib for inferred architecture x86_64
Don't even know what that might mean.
ld needs -lSystem flag to prevent it from throwing this error. Also it needs -macosx_version_min to remove the warning. The correct way of using ld would be: ld hello.o -o hello -macosx_version_min 10.13 -lSystem.
Updated on macOS 11 and above, you need to pass -L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib as well so that it locates the -lSystem library correctly. You can use -L$(xcode-select -p)/SDKs/MacOSX.sdk/usr/lib to evaluate the right path dynamically if required.
In addition to the #Verloren answer above (https://stackoverflow.com/a/52830915/1189569)
I had an issue with macOS Big Sur (macOS 11.1), where flag -lSystem could not locate libSystem.dylib, with the error
ld: library not found for -lSystem
I found out for macOS Big Sur, quoted from the link:
https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11_0_1-release-notes
New in macOS Big Sur 11.0.1, the system ships with a built-in dynamic
linker cache of all system-provided libraries. As part of this change,
copies of dynamic libraries are no longer present on the filesystem.
Code that attempts to check for dynamic library presence by looking
for a file at a path or enumerating a directory will fail...
that all copies of dynamic libraries are not located in usr/lib/ and similar, so flag -lSystem could not found libSystem.dylib by default.
The solution to this was to update/install the latest version of Command Line Tools, if not already, and to set flag -L of the ld command to /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib.
So full command would look like this:
ld hello.o -o hello -macosx_version_min 11.0 -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem
Simpler answer. ld is defaulting to dynamic linking and tries to load crt1 which is looking for main. So specify static linking.
% ld -e start -static hello.o -o hello
% ./hello
Hello world!
In macOS 11.2 i used:
ld hello.o -L /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib -lSystem

yasm writing to PAGEZERO in x86_64 mach-o format

I'm following a assembly book which uses the yasm assembler and ld linker. I'm on OSX 10.12 and I'm trying to assembly to Mach-O format. Unfortunately, I'm receiving a segmentation fault. This is the original .asm file:
BITS 64
segment .data
a dd 4
segment .bss
g resd 1
segment .text
global start
start:
push rbp
mov rbp, rsp
sub rsp, 16
xor eax, eax
leave
ret
I compile it:
yasm -f macho64 -m amd64 -l memory.lst -o memory.o memory.asm
link it:
ld memory.o -o memory
and run it in lldb, I receive this error:
thread #1: tid = 0xb3b4b, 0x0000000000000001, stop reason = EXC_BAD_ACCESS (code=1, address=0x1)
frame #0: 0x0000000000000001
error: error reading data from section __PAGEZERO
In lldb, I ran 'target modules dump sections', and I see that it's __PAGEZERO segment is defined as so:
[0x0000000000000000-0x0000000000001000) --- memory.__PAGEZERO
I looked at a normal Mach-O binary built with clang, and the __PAGEZERO segment looks like this:
[0x0000000000000000-0x0000000100000000) --- test.__PAGEZERO
I then noticed that it's actually the linker that creates the PAGEZERO segment. I believe clang uses a special linker called 'lld'. My question is:
Is my error actually caused by reading from PAGEZERO.
If so, can I tell my linker (ld) to define PAGEZERO in the correct size?
SOLVED: I changed the link command to:
ld memory.o -macosx_version_min 10.12 -lSystem -o memory
This doesn't change the PAGEZERO size, so I'm not sure how it fixed it, but it works now.

Why do common C compilers include the source filename in the output?

I have learnt from this recent answer that gcc and clang include the source filename somewhere in the binary as metadata, even when debugging is not enabled.
I can't really understand why this should be a good idea. Besides the tiny privacy risks, this happens also when one optimizes for the size of the resulting binary (-Os), which looks inefficient.
Why do the compilers include this information?
The reason why GCC includes the filename is mainly for debugging purposes, because it allows a programmer to identify from which source file a given symbol comes from as (tersely) outlined in the ELF spec p1-17 and further expanded upon in some Oracle docs on linking.
An example of using the STT_FILE section is given by this SO question.
I'm still confused why both GCC and Clang still include it even if you specify -g0, but you can stop it from including STT_FILE with -s. I couldn't find any explanation for this, nor could I find an "official reason" why STT_FILE is included in the ELF specification (which is very terse).
I have learnt from this recent answer that gcc includes the source filename somewhere in the binary as metadata, even when debugging is not enabled.
Not quite. In modern ELF object files the file name indeed is a symbol of type FILE:
$ readelf bignum.o # Source bignum.c
[...]
Symbol table (.symtab) contains 36 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS bignum.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 8
9: 00000000000003f0 172 FUNC GLOBAL DEFAULT 1 add
10: 00000000000004a0 104 FUNC GLOBAL DEFAULT 1 copy
However, once stripped, the symbol is gone:
$ strip bignum.o
$ readelf -all bignum.o | grep bignum.c
$
So to keep your privacy, strip the executable, or compile/link with -s.

GCC: -static and -pie are incompatible for x86?

I'm recompiling some executable for Android 5.0 as it requires executables to be PIE. I was able to recompile it for ARM with just adding some arguments while configuring (with standalone toolchain):
export CFLAGS="-I/softdev/arm-libs/include -fPIE"
export CPPLAGS="$CPPFLAGS -fPIE"
export CXXLAGS="$CXXFLAGS -fPIE"
export LDFLAGS="-L/softdev/arm-libs/lib -static -fPIE -pie"
No error for ARM:
configure:3406: arm-linux-androideabi-gcc -o conftest -I/softdev/arm-libs/include -fPIE -L/softdev/arm-libs/lib -static -fPIE -pie conftest.c >&5
configure:3410: $? = 0
But i was unable to do the same for x86 as i'm getting error:
export CFLAGS="-I/softdev/x86-libs/include -fPIE"
export CPPLAGS="$CPPFLAGS -fPIE"
export CXXLAGS="$CXXFLAGS -fPIE"
export LDFLAGS="-L/softdev/x86-libs/lib -static -fPIE -pie"
error:
configure:3336: i686-linux-android-gcc -I/softdev/x86-libs/include -fPIE -L/softdev/x86-libs/lib -static -fPIE -pie conftest.c >&5
/softdev/x86-toolchain-gcc4.8/bin/../lib/gcc/i686-linux-android/4.8/../../../../i686-linux-android/bin/ld: fatal error: -pie and -static are incompatible
collect2: error: ld returned 1 exit status
configure:3340: $? = 1
I need executables to be linked statically. What's wrong and how can i fix it?
PS. Also tried using x86 standalone toolchain from android ndk r9d and r10c:
./make-standalone-toolchain.sh --toolchain=x86-4.8 --arch=x86 --install-dir=/softdev/x86-toolchain-gcc4.8-r9d --ndk-dir=/softdev/android-ndk-r9d/ --system=darwin-x86_64
As mentioned by n4sm below gcc-8 or later supports -static-pie which produces a static binary with PIE. Note that is one option not two. If you try to use -static -pie it will not do what you think.
I just did quick test with the fallowing in te.c:
int main( int argc, const char* argv[] )
{
reyurn 0;
}
Running arm-linux-androideabi-gcc -o conftest -static -FPIE -pie te.c produces no error. However file -k conftest outputs
conftest: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), not stripped
readelf -l conftest outputs
Elf file type is DYN (Shared object file)
Entry point 0x500
There are 7 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00000034 0x00000034 0x000e0 0x000e0 R 0x4
INTERP 0x000114 0x00000114 0x00000114 0x00013 0x00013 R 0x1
[Requesting program interpreter: /system/bin/linker]
...
The presence of the PHDR and INTERP headers indicates that -pie silently overrides -static in the arm compiler. Why this is I don't know but I would consider it a bug that no warning is given when -static and -pie are used together. Instead programmers like you are left with the false impression that the two options can be used to together on arm.
Just to clarify the only behavioral difference here is that the x86 compiler errors on seeing both --static and --pie whereas the arm version silently ignores --static if --pie is given. If only one these is given the behavior is the same for both compilers.
If -pie and -static are both given together, gcc will issue unexpected error.
-pie
Produce a position independent executable on targets that support it. For predictable results, you must also specify the same set of options used for compilation (-fpie, -fPIE, or model suboptions) when you specify this linker option.
-pie actually create a DYN type elf file with INTERP with /system/bin/linker
executable compiled with -pie
-static
On systems that support dynamic linking, this prevents linking with the shared libraries. On other systems, this option has no effect.
-static create a EXEC type elf file with no INTERP
Now it's directly possible with the -static-pie option!
For example:
#include <stdio.h>
/* /tmp/test.c */
int main(int argc, char **argv) {
printf("Hello world!\n");
}
You have just to use the -static-pie option:
gcc /tmp/test.c -static-pie -o /tmp/test
And with readelf we got this:
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000008158 0x0000000000008158 R 0x1000
LOAD 0x0000000000009000 0x0000000000009000 0x0000000000009000
0x000000000009473d 0x000000000009473d R E 0x1000
LOAD 0x000000000009e000 0x000000000009e000 0x000000000009e000
0x00000000000284b8 0x00000000000284b8 R 0x1000
LOAD 0x00000000000c6de0 0x00000000000c7de0 0x00000000000c7de0
0x0000000000005370 0x0000000000006a80 RW 0x1000
DYNAMIC 0x00000000000c9c18 0x00000000000cac18 0x00000000000cac18
0x00000000000001b0 0x00000000000001b0 RW 0x8
NOTE 0x00000000000002e0 0x00000000000002e0 0x00000000000002e0
0x0000000000000020 0x0000000000000020 R 0x8
NOTE 0x0000000000000300 0x0000000000000300 0x0000000000000300
0x0000000000000044 0x0000000000000044 R 0x4
TLS 0x00000000000c6de0 0x00000000000c7de0 0x00000000000c7de0
0x0000000000000020 0x0000000000000060 R 0x8
GNU_PROPERTY 0x00000000000002e0 0x00000000000002e0 0x00000000000002e0
0x0000000000000020 0x0000000000000020 R 0x8
GNU_EH_FRAME 0x00000000000ba130 0x00000000000ba130 0x00000000000ba130
0x0000000000001c8c 0x0000000000001c8c R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x00000000000c6de0 0x00000000000c7de0 0x00000000000c7de0
0x0000000000003220 0x0000000000003220 R 0x1
I don't know since when we can use this option, but for me, I'm using gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Google's NDK tool contain some info about PIE usage.
Visit build/core/build-binary.mk, see line 209. It says:
# enable PIE for executable beyond certain API level, unless "-static"
I guess, it is linux dynamic link principle's limit.
Because Android interpreter (/system/bin/linker) determining which address elf file to be loaded in a static linked file has no interpreter, elf file will be mapped to memory into a fixed address by linux kernel.
Here is a discuss about this change Google issue
If I have any mistake please figure it out:)

Resources