Linking with cygwin - c

I have a small program that's made of an assembly function and a C function which calls it.
Now the program compiles and works perfectly on a UNIX system but when using the makefile in cygwin i get the following error:
gcc -m32 -g -c -o main.o main.c
gcc -g -m32 -o ass0 main.o myasm.o
main.o: In function main':
/cygdrive/c/ass0/main.c:15: undefined reference to_strToLeet'
collect2: error: ld returned 1 exit status
makefile:3: recipe for target 'ass0' failed
make: *** [ass0] Error 1
code of the main.c file :
#include <stdio.h>
# define MAX_LEN 100 // Maximal line size
extern int strToLeet (char*);
int main(void) {
char str_buf[MAX_LEN];
int str_len = 0;
printf("Enter a string: ");
fgets(str_buf, MAX_LEN, stdin); // Read user's command line string
str_len = strToLeet (str_buf); // Your assembly code function
printf("\nResult string:%s\nNumber of letters converted to Leet: %d\n",str_buf,str_len);
}
start of assembly code:
section .data ; data section, read-write
an: DD 0 ; this is a temporary var
section .text ; our code is always in the .text section
global strToLeet ; makes the function appear in global scope
extern printf ; tell linker that printf is defined elsewhere
strToLeet: ; functions are defined as labels
push ebp ; save Base Pointer (bp) original value
mov ebp, esp ; use base pointer to access stack contents
pushad ; push all variables onto stack
mov ecx, dword [ebp+8] ; get function argument
makefile code :
all: ass0
ass0: main.o myasm.o
gcc -g -m32 -o ass0 main.o myasm.o
main.o: main.c
gcc -m32 -g -c -o main.o main.c
myasm.o: myasm.s
nasm -g -f elf -l ass0list -o myasm.o myasm.s
help would be most appriciated

Solved by user 'tvin' -
Try to modify your prototype to become extern int strToLeet (char*) asm ("strToLeet"); – tivn

Related

How to call external c file from assembly?

I'm tried this below tools, to call 2 files
My idea was to execute the function from c using assembler and create a bin file
nasm -f elf32 boot3.s -o boot3.o // convert asm file to object
gcc -c bootloader3.c -o bootloader3.o // convert c file to object
gcc boot3.o bootloader3.o -o boot3.bin // make bin file
boot3.s
section .text
bits 16
global _start ; Declare the entry point symbol
extern main ; Declare the main function as external
_start:
cli ; Disable the interrupts
call main ; Call the main function
hlt ; Halt the CPU
bootloader3.c
#include <stdio.h>
void main() {
printf("Hello, World!\n");
return;
}
My error: Error Image
Update 05.01.23
I tried to use a similar method, but with other commands, unfortunately another attempt also failed.
boot.s
bits 16
extern main
start:
cli ; Disable the interrupts
mov si, msg ; SI now points to our message
mov ah, 0x0E ; Indicate BIOS we're going to print chars
.loop lodsb ; Loads SI into AL and increments SI [next char]
or al, al ; Checks if the end of the string
jz halt ; Jump to halt if the end
int 0x10 ; Otherwise, call interrupt for printing the char
jmp .loop ; Next iteration of the loop
halt: hlt ; CPU command to halt the execution
msg: db "Hello, World!", 0 ; Our actual message to print
section .text
global puts
puts:
; Insert code for the puts function here
times 510 - ($ - $$) db 0
; Add the boot signature
dw 0xAA55
bootloader.c
//extern void puts(const char* str);
int main(void)
{
puts("Hello user");
return 0;
}
Compile using tools
First Step
nasm -f elf64 boot.s -o boot.o
gcc -c -m32 -o bootloader.o bootloader.c
ld -Ttext=0x7C00 -o boot.elf boot.o bootloader.o
Second Step
nasm -f bin boot.s -o boot.o
gcc -c -m32 -o bootloader.o bootloader.c
gcc -m32 -nostdlib -nostartfiles -Wl,-Ttext,0x7C00 boot.o bootloader.c -o boot.elf
Third Step
nasm -f elf32 boot.s -o boot.o
gcc -c -m32 -o bootloader.o bootloader.c
ld -Ttext=0x7C00 -o boot.elf boot.o bootloader.o
My Error:
On First & Third step
ld: bootloader.o:bootloader.c:(.text+0xa): undefined reference to `__main' ld: bootloader.o:bootloader.c:(.text+0x16): undefined reference to `puts'
On Seconds step
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Klubuntu\AppData\Local\Temp\ccojaMyU.o:bootloader.c:(.text+0xa): undefined reference to `__main' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Klubuntu\AppData\Local\Temp\ccojaMyU.o:bootloader.c:(.text+0x16): undefined reference to `puts' collect2.exe: error: ld returned 1 exit status
Sorry for all grammar mistakes
Thanks from above help

Archive has no index; run ranlib to add one (when linking with a .a containing a MachO64 object file on Linux)

I tried to create a library and test it, but an error occurred.
error code:
./libasm.a: error adding symbols: Archive has no index; run ranlib to add one
collect2: error: ld returned 1 exit status
I compiled it like this.
nasm -f macho64 ft_strlen.s -o ft_strlen.o
ar rcs libasm.a ft_strlen.o
ranlib libasm.a
gcc main.c libasm.a
Below is the source file
;ft_strlen.s
segment .text
global ft_strlen
ft_strlen:
mov rax, 0
jmp count
count:
cmp BYTE [rdi + rax], 0
je exit
inc rax
jmp count
exit:
ret
/*main.c*/
#include <stdio.h>
int ft_strlen(char *str);
int main(void)
{
char *str = "hello world";
printf("%d \n", ft_strlen(str));
}
I am using ubuntu installed on wsl.
What am I doing wrong?
Generate object files for Linux-based operating system (or perhaps more correctly, and ELF64 system) with nasm -f elf64 ft_strlen.s -o ft_strlen.o
For more info nasm -hf to see all valid output formats for nasm -f
Small tip: ranlib command is not needed because ar s is already indexing the library.

Call an assembler function from C code in linux [duplicate]

This question already has answers here:
32-bit absolute addresses no longer allowed in x86-64 Linux?
(1 answer)
What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?
(1 answer)
Assembling 32-bit binaries on a 64-bit system (GNU toolchain)
(2 answers)
Closed 3 years ago.
I want to call a print function from my C program.
assembler prog:
#test.s
.text
.global _start
.global print
.type print, #function
_start:
call print
# and exit.
movl $0,%ebx # first argument: exit code.
movl $1,%eax # system call number (sys_exit).
int $0x80 # call kernel.
print:
# write our string to stdout.
movl $len,%edx # third argument: message length.
movl $msg,%ecx # second argument: pointer to message to write.
movl $1,%ebx # first argument: file handle (stdout).
movl $4,%eax # system call number (sys_write).
int $0x80 # call kernel.
mov $0, %eax
ret
.data
msg:
.ascii "Hello, world!\n" # the string to print.
len = . - msg # length of the string.
I can assemble and link it using:
$as test.s -o test.o
$ld test.o -o test
And I can execute it as a program, and it outputs "Hello, world!"
But when I tried to call a print from C code like this:
#include <stdio.h>
extern int print();
int main(){
int g;
g = print();
printf("Hello from c!, %d\n", g);
}
It was compiled using:
$gcc -c main.c test
It just prints "Hello from c, 13", that means that the function was called and return a number of chars, but does not print anything!
What am I doing wrong?
P.S.
When I trying to compile prog like this:
$as test.s -o test.o
$gcc -c main.c -o main.o
$gcc main.c test.o
I have a error:
/usr/bin/ld: test.o: in function `_start':
(.text+0x0): multiple definition of `_start'; /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/Scrt1.o:(.text+0x0): first defined here
/usr/bin/ld: test.o: relocation R_X86_64_32 against `.data' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
Ok, done! Thanks clearlight
I can compile all use
$as test.s -o test.o
$gcc -c main.c -o main.o
$gcc -no-pie main.c test.o
And all will work fine!

How to fix ".c:6: undefined reference to 'printf'

I am freshman, I want to learn about ARM assembly language and using gnu toolchain so I decided to start with small project that mixes arm-assembly file and C file by gnu toolchain. My idea is calling a function that is defined in assembly file.
multi.S:
.globl multi
multi:
str fp,[sp,#-4]!
add fp,sp,#0
sub sp,sp,#12
str r0,[fp,#-8]
str r1,[fp,#-12]
ldr r3,[fp,#-8]
ldr r2,[fp,#-12]
mul r1,r2,r3
mov r3,r1
mov r0,r3
add sp,fp,#0
ldr fp,[sp],#4
bx lr
multi.c:
#include <stdio.h>
unsigned int multi(unsigned int a, unsigned int b);
int main(int argc, char *argv[]){
unsigned int x = multi(3,4);
printf("%u\n",x);
return 0;
}
Then I tried to link them together by using command as follows:
arm-none-eabi-gcc -g -c -o multi-arm.o multi.S
arm-none-eabi-gcc -g -c -o multi.o multi.c
arm-none-eabi-ld multi.o multi-arm.o -o multi.elf
But there's some errors occurred:
warning: can not find entry symbol _start; defaulting to 0000000082000000
=> I solved this problem by adding -lc --entry main and the warning message is gone.
multi.c:6: undefined reference to 'printf'. I am stuck with this error and it took me 2 hours searching for sulution but I still can't not fix it.
Above is my question.
Thank you all for reading.
Try this
arm-none-eabi-as -g -o multi-arm.o multi.S
arm-none-eabi-gcc -g -o multi.elf multi.c multi-arm.o
If you want to use the linker directly then you have to provide the path to the C library on the command line. Gcc knows where the library is (relative to where it executes from and was compiled for) when it calls the linker, but for some strange reason ld does not.

Commands to compile ASM file with C program [duplicate]

This question already has an answer here:
32-bit absolute addresses no longer allowed in x86-64 Linux?
(1 answer)
Closed 4 years ago.
with à 64 Linux system and using NASM.
I'm trying too link my ASM (hello.asm) file with a C file (main.c) and compile to a execution file.
I create a ASM file that print "Hello" with printf by using printHello function.
extern printf, exit
section .data
format db "Hello", 10, 0
section .text
global printHello
printHello:
sub rsp, 8
mov rsi, 0x12345677
mov rdi, format
xor rax, rax
call printf
mov rdi, 0
call exit
I create a simple main.c and call my function "printHello" to print "Hello"
#include <stdio.h>
void printHello();
int main()
{
printHello();
}
My command for compile :
$ nasm -f elf64 hello.asm
$ gcc -c main.c
$ gcc -o executable main.o hello.o
$ ./executable
And it prints :
./executable: Symbol `printf' causes overflow in R_X86_64_PC32 relocation
./executable: Symbol `exit' causes overflow in R_X86_64_PC32 relocation
[1] 6011 segmentation fault ./executable
I'm already learning ASM. Is the problem come from my command or my code ?
I resolved the problem by using your #Jester solution :
gcc -no-pie -o executable main.o hello.o
and thanks Ped7g for explanation.

Resources