Kawaxi
Kawaxi

Reputation: 13

Problems with compiled gcc .s Code when linking

First time here, Im running Kali linux 64bits ,Im a linux rookie and a new to ASM aswell.... So I pulled a code in C ,the wich works perfectly fine..... here is the code:

#include<stdio.h>
#include<string.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr

int main(int argc , char *argv[])
{
int socket_desc;
struct sockaddr_in server;
char *message , server_reply[2000];

//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
    printf("Could not create socket");
}

server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( 2000 );

//Connect to remote server
if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) <0)
{
    puts("connect error");
    return 1;
}

puts("Connected\n");

//Send some data
message = "Hola!!!!\n\r\n";
if( send(socket_desc , message , strlen(message) , 0) < 0)
{
    puts("Send failed");
    return 1;
}
puts("Data Send\n");

//Receive a reply from the server
if( recv(socket_desc, server_reply , 2000 , 0) < 0)
{
    puts("recv failed");
}
puts("Reply received\n");
puts(server_reply);

return 0;
}

So ... I use gcc -S -o example.s example.c , to get the ASM code... wich is:

.file   "test.c"
.section    .rodata
.LC0:
.string "Could not create socket"
.LC1:
.string "127.0.0.1"
.LC2:
.string "connect error"
.LC3:
.string "Connected\n"
.align 8
.LC4:
.string "Hola!!  , \n\r\n"
.LC5:
.string "Send failed"
.LC6:
.string "Data Send\n"
.LC7:
.string "recv failed"
.LC8:
.string "Reply received\n"
.text
.globl  main
.type   main, @function
main:
.LFB2:
.cfi_startproc
pushq   %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq    %rsp, %rbp
.cfi_def_cfa_register 6
subq    $2048, %rsp
movl    %edi, -2036(%rbp)
movq    %rsi, -2048(%rbp)
movl    $0, %edx
movl    $1, %esi
movl    $2, %edi
call    socket
movl    %eax, -4(%rbp)
cmpl    $-1, -4(%rbp)
jne .L2
movl    $.LC0, %edi
movl    $0, %eax
call    printf
.L2:
movl    $.LC1, %edi
call    inet_addr
movl    %eax, -28(%rbp)
movw    $2, -32(%rbp)
movl    $2000, %edi
call    htons
movw    %ax, -30(%rbp)
leaq    -32(%rbp), %rcx
movl    -4(%rbp), %eax
movl    $16, %edx
movq    %rcx, %rsi
movl    %eax, %edi
call    connect
testl   %eax, %eax
jns .L3
movl    $.LC2, %edi
call    puts
movl    $1, %eax
jmp .L7
.L3:
movl    $.LC3, %edi
call    puts
movq    $.LC4, -16(%rbp)
movq    -16(%rbp), %rax
movq    %rax, %rdi
call    strlen
movq    %rax, %rdx
movq    -16(%rbp), %rsi
movl    -4(%rbp), %eax
movl    $0, %ecx
movl    %eax, %edi
call    send
testq   %rax, %rax
jns .L5
movl    $.LC5, %edi
call    puts
movl    $1, %eax
jmp .L7
.L5:
movl    $.LC6, %edi
call    puts
leaq    -2032(%rbp), %rsi
movl    -4(%rbp), %eax
movl    $0, %ecx
movl    $2000, %edx
movl    %eax, %edi
call    recv
testq   %rax, %rax
jns .L6
movl    $.LC7, %edi
call    puts
.L6:
movl    $.LC8, %edi
call    puts
leaq    -2032(%rbp), %rax
movq    %rax, %rdi
call    puts
movl    $0, %eax
.L7:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size   main, .-main
.ident  "GCC: (Debian 4.9.2-10) 4.9.2"

So after using as example.s -o example.o, I use ld example.o -o example, and thats where I get these following errors:

ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0 test.o: In function main': test.c:(.text+0x28): undefined reference tosocket' test.c:(.text+0x40): undefined reference to printf' test.c:(.text+0x4a): undefined reference toinet_addr' test.c:(.text+0x5d): undefined reference to htons' test.c:(.text+0x77): undefined reference toconnect' test.c:(.text+0x85): undefined reference to puts' test.c:(.text+0x99): undefined reference toputs' test.c:(.text+0xad): undefined reference to strlen' test.c:(.text+0xc3): undefined reference tosend' test.c:(.text+0xd2): undefined reference to puts' test.c:(.text+0xe3): undefined reference toputs' test.c:(.text+0xfe): undefined reference to recv' test.c:(.text+0x10d): undefined reference toputs' test.c:(.text+0x117): undefined reference to puts' test.c:(.text+0x126): undefined reference toputs'

it seems to me that gcc is not usingn correctly .start, global main, etc. but to be honest I wouldnt know how to fix it., if this is correct then why?

Any help Will be appreciate.

Thank you.

Upvotes: 0

Views: 1654

Answers (4)

The commands given in Harry's answer are the good ones:

gcc -Wall -O -fverbose-asm -S example.c
gcc -c example.s -o example.o
gcc  example.o -o example

Basically, you should be aware that GCC would link your code with :

How all this is linked together is known by the gcc command, which will start some ld. Replace gcc with gcc -v in your compilation commands to understand what exactly is happening. If you want to issue your own ld command you should add the options providing what I have listed above. The errors you are getting are notably because of the lack of crt0 & libc

BTW on Linux most C standard libraries (e.g. GNU libc or musl-libc) are free software (and so is GCC), so you can study their source code.

Try also gcc -dumpspecs which describes what gcc knows about issuing various commands (notice that gcc is only a driving program; the real C compiler is some cc1). Read also the wikipage on GCC. Some slides and references on the documentation of GCC MELT gives a lot more information. See also this and the picture there.

I strongly recommend to also use gcc to assemble (some assembler code of yours) and to link stuff (because you don't want to handle all the gory details mentioned above, plus some other ones I did not mention).

Upvotes: 2

user58697
user58697

Reputation: 7923

This is an important part:

/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/4.9/crtbegin.o
-lgcc 
--as-needed -lgcc_s
--no-as-needed -lc -lgcc
--as-needed -lgcc_s
--no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.9/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crtn.o

crt1, crti, crtbegin supply the startup code where the _start entry point is actually defined (later on the control is passed to your main), stdio is initialized, etc. Similarly strand and crtn handle the cleanup after main return. lc supplies the standard library (like puts and other missing symbols). lgcc and lgcc_s have the gcc-specific runtime support.

The bottomline is, you need all that to be linked in.

Upvotes: 1

Harry
Harry

Reputation: 11648

Try this

gcc -Wall -O -fverbose-asm -S example.c
gcc -c example.s -o example.o
gcc  example.o -o example

Upvotes: 1

user58697
user58697

Reputation: 7923

The problem is that ld example.o -o example tries to link just example.o and nothing else. To get missing symbols you need to link much more (e.g. startup code, standard library, C runtime, etc). Try gcc -v example.c to see how the linker should be invoked.

Upvotes: 2

Related Questions