Other Call C functions in ASM

Hi guys

I am trying to call functions from the C library in my ASM code. For example I prefer to use printf before doing a syscall to write.

So I disassembled a simple binary and could see that a call to printf derives to the PLT section.

That if I'm not mistaken is a link table, since printf being outside my code, it has to create the address in the execution. Of course when trying to call printf with a callq printf@plt in my ASM code it doesn't work, I haven't linked any libraries.

Well, what would be the correct way to link all those libraries, through clang or ld?

Some example of what would be the best way.

Thanks guys.
 
The C runtime does some initialization before calling main. If your code provides a main function, you should be able to link it to -lstdc with ld. You'd need to pass the same flags that clang would provide for a simple hello.c compile and link.

The alternative is to write an actual main.c function and link your asm code as object files or a library.
 
To link you can use ld or gcc.
To have a start code i would write a hello world in C and then compile this to assembly using "cc -S" or "gcc -S"
 
The C runtime does some initialization before calling main. If your code provides a main function, you should be able to link it to -lstdc with ld. You'd need to pass the same flags that clang would provide for a simple hello.c compile and link.

The alternative is to write an actual main.c function and link your asm code as object files or a library.
To link you can use ld or gcc.
To have a start code i would write a hello world in C and then compile this to assembly using "cc -S" or "gcc -S"

I understand what you are telling me, use clang to assemble my code and link to the following libraries.

root@eclipse:~ # clang -v -m64 code.S
FreeBSD clang version 11.0.1 (git@github.com:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)
Target: x86_64-unknown-freebsd13.0
Thread model: posix
InstalledDir: /usr/bin
"/usr/bin/clang" -cc1 -triple x86_64-unknown-freebsd13.0 -E -disable-free -disable-llvm-verifier -discard-value-names -main-file-name code.S -mrelocation-model static -mframe-pointer=all -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /usr/lib/clang/11.0.1 -fdebug-compilation-dir /root -ferror-limit 19 -fgnuc-version=4.2.1 -fcolor-diagnostics -faddrsig -o /tmp/code-adfbdf.s -x assembler-with-cpp code.S
clang -cc1 version 11.0.1 based upon LLVM 11.0.1 default target x86_64-unknown-freebsd13.0
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/clang/11.0.1/include
/usr/include
End of search list.
"/usr/bin/clang" -cc1as -triple x86_64-unknown-freebsd13.0 -filetype obj -main-file-name code.S -target-cpu x86-64 -fdebug-compilation-dir /root -dwarf-debug-producer "FreeBSD clang version 11.0.1 (git@github.com:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)" -dwarf-version=4 -mrelocation-model static -o /tmp/code-cb23fc.o /tmp/code-adfbdf.s
"/usr/bin/ld" --eh-frame-hdr -dynamic-linker /libexec/ld-elf.so.1 --hash-style=both --enable-new-dtags -o a.out /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /tmp/code-cb23fc.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/crtend.o /usr/lib/crtn.o
I understand that in order to do the ld I have to link the libraries that appear in -dynamic-linker.

But apparently I can't pass addresses from the data section, it generates a bus error. Same when I pass address of the stack.

Code:
.section .text
.globl main

main:

movq $0x4141414141414141, %rbx
pushq %rbx
pushq %rbx
pushq %rbx
movq %rsp, %rdi
call printf

call exit
#movq $1, %rax     ### syscall exit
#syscall

That is the simple code I have, I copy a string from "A" to the stack and then pass the pointer to printf so that it prints the message on the screen.

But if I want it to print the second string I have to load the string three times on the stack, if not when executing it it will give a core dumped.

I guess the stack is not aligned or some similar error, if anyone knows something please tell me.

Now I know what I have to do to be able to pass the libraries with ld.

What compiler do you use for asm code?
I coded a few with NASM and it's rather easy to call C functions. See here.

Not to forget the matching between arguments and registers which was one of my two mistakes: https://forums.freebsd.org/threads/basic-assembly-programming.65515/post-384582

I am using GAS, if I know I think it is not necessary, since I had to install binutils from the ports.

GAS is not in the base system, since I assume that clang replaces it.

Thanks guys.
 
I think it's as(1) for FreeBSD. It's in the base system.

Actually, you have to make some sort of stack alignement with 64 bits assembly:
Code:
sub rsp,8  ; stack alignement

This is for NASM, don't know if it applies to GAS or as.
 
Allow to give an example.
The following program ,
Code:
#include <unistd.h>
int main(void)
{
    write(1, "Hello world\n", 12);
    return 0;
}
With "cc -S" creates assembly
Code:
    .text
    .file   "test.c"
    .globl  main                            # -- Begin function main
    .p2align    4, 0x90
    .type   main,@function
main:                                   # @main
    .cfi_startproc
# %bb.0:
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movl    $0, -4(%rbp)
    movl    $1, %edi
    movabsq $.L.str, %rsi
    movl    $12, %edx
    callq   write
    xorl    %ecx, %ecx
    movq    %rax, -16(%rbp)                 # 8-byte Spill
    movl    %ecx, %eax
    addq    $16, %rsp
    popq    %rbp
    .cfi_def_cfa %rsp, 8
    retq
.Lfunc_end0:
    .size   main, .Lfunc_end0-main
    .cfi_endproc
                                        # -- End function
    .type   .L.str,@object                  # @.str
    .section    .rodata.str1.1,"aMS",@progbits,1
.L.str:
    .asciz  "Hello world\n"
    .size   .L.str, 13

    .ident  "FreeBSD clang version 11.0.1 (git@github.com:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)"
    .section    ".note.GNU-stack","",@progbits
    .addrsig
    .addrsig_sym write
 
I think it's as(1) for FreeBSD. It's in the base system.

Actually, you have to make some sort of stack alignement with 64 bits assembly:
Code:
sub rsp,8  ; stack alignement

This is for NASM, don't know if it applies to GAS or as.
Yes, the order for GAS is (1) as. But in my case it was not found, I had to install the binutils package to get GAS.

I install my FreeBSD from disc1, possibly it should have the minimum packages.

On the other hand, I already tried to subtract the stack, without any result it must be some fault of mine, printf is printing more values than it should, it would have to end when finding zero.

Allow to give an example.
The following program ,
Code:
#include <unistd.h>
int main(void)
{
    write(1, "Hello world\n", 12);
    return 0;
}
With "cc -S" creates assembly
Code:
    .text
    .file   "test.c"
    .globl  main                            # -- Begin function main
    .p2align    4, 0x90
    .type   main,@function
main:                                   # @main
    .cfi_startproc
# %bb.0:
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movl    $0, -4(%rbp)
    movl    $1, %edi
    movabsq $.L.str, %rsi
    movl    $12, %edx
    callq   write
    xorl    %ecx, %ecx
    movq    %rax, -16(%rbp)                 # 8-byte Spill
    movl    %ecx, %eax
    addq    $16, %rsp
    popq    %rbp
    .cfi_def_cfa %rsp, 8
    retq
.Lfunc_end0:
    .size   main, .Lfunc_end0-main
    .cfi_endproc
                                        # -- End function
    .type   .L.str,@object                  # @.str
    .section    .rodata.str1.1,"aMS",@progbits,1
.L.str:
    .asciz  "Hello world\n"
    .size   .L.str, 13

    .ident  "FreeBSD clang version 11.0.1 (git@github.com:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)"
    .section    ".note.GNU-stack","",@progbits
    .addrsig
    .addrsig_sym write


Yes I understand, but I don't want to transform C code into ASM. I already used a Hello world in C to find out about the @plt section, with a combination of readelf and objdump.

My idea was to know a little more, about how to use external libraries in ASM (pure), since not everything is in syscall.

The alternative is to write an actual main.c function and link your asm code as object files or a library.

If that's a good idea, I already tried using ASM inline or writing some function / routine in ASM, but in the end I'm more comfortable in ASM.

In my study center, they make us write the codes in JAVA.

ASM I take it as a hobby, I write cipher routines like AES, optimized functions with the SSE2,3 instructions, etc.

Also because I like to know more or less what we are doing, with JAVA we don't have those options.

Thanks guys
 
Some yell if i'm wrong (i'm new on freebsd). in linux you cannot - the ties to libc and applications is ... "way too devious" to comprehend.

I WOULD NOT DO what your planning in Unix (to call the C library) because you need the C startup code "i will say - for various reasons". You should make Hello World program compiled with gcc and have it call a .o you made using ASM instead.

remember what your doing is now considered "virus code" and would be deleted by Microsoft's canaries. i'm not saying that's good i'm saying that's what they've definitely done

if you check GCC's options you'll find it will print out, if you ask, all the modules, locations of files, and the order they are used when linking - everything you need to know (but shouldn't do - don't call libc from asm call ASM from C or call the OS from asm - unless someone posts full code of how to do it safely - i've never seen that done maybe someone has it hoarded somewheres)
 
Some yell if i'm wrong (i'm new on freebsd). in linux you cannot - the ties to libc and applications is ... "way too devious" to comprehend.

I WOULD NOT DO what your planning in Unix (to call the C library) because you need the C startup code "i will say - for various reasons". You should make Hello World program compiled with gcc and have it call a .o you made using ASM instead.

remember what your doing is now considered "virus code" and would be deleted by Microsoft's canaries. i'm not saying that's good i'm saying that's what they've definitely done

if you check GCC's options you'll find it will print out, if you ask, all the modules, locations of files, and the order they are used when linking - everything you need to know (but shouldn't do - don't call libc from asm call ASM from C or call the OS from asm - unless someone posts full code of how to do it safely - i've never seen that done maybe someone has it hoarded somewheres)
I coded in ASM on FreeBSD and Windows, calling C functions. This works perfectly. I didn't bother with any C startup code. That works, dot.

That being said, I recall that it happened some antivirus software got red under Windows.
 
Back
Top