Linux X86-64 assembly and printf - linux

I am reading some linux assembly manuals and found idea about using printf() function. I need it to output register values for debugging reasons in binary form to terminal, but now I am tried simply to test that function with text.
I am stuck, because of segfault when I am using pushq instead of pushl. How can I change this program to output strings and binary form of registers?
.data
input_prompt:
.string "Hello, world!"
printf_format:
.string "%5d "
printf_newline:
.string "\n"
size:
.long 0
.text
.globl main
main:
pushq $input_prompt
call printf
movl $0, %eax
ret
It was compiled by GCC as:
gcc tmp.S -o tmp

Linux (and Windows) x86-64 calling convention has the first few arguments not on the stack, but in registers instead
See http://www.x86-64.org/documentation/abi.pdf (page 20)
Specifically:
If the class is MEMORY, pass the argument on the stack.
If the class is INTEGER, the next available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used.
If the class is SSE, the next available vector register is used, the registers are taken in the order from %xmm0 to %xmm7.
If the class is SSEUP, the eightbyte is passed in the next available eightbyte chunk of the last used vector register.
If the class is X87, X87UP or COMPLEX_X87, it is passed in memory.
The INTEGER class is anything that will fit in a general purpose register, so that's what you would use for string pointers as well.

Related

.struct directive of GNU Assembler - How to instantiate a class instance?

I'm trying to create an object-oriented class using GNU assembly for educational purposes. I have many questions regarding the use of the .struct directive:
It is said that this directive switch the code to the absolute section. Why is it named .struct then? Does it have anything to do with the struct of C?
What is the difference between using:
.set Object.data, 8
.set Object.func_pointer, 16
and using
.struct 0
Object:
Object.data:
.struct Object + 8
Object.func_pointer:
.struct Object.data + 8
Object_size = . - Object
Is this actually the way to use the .struct directive or it it a miss-use? To be honest I don't even know what I'm doing with the .struct directive. It looks useless to me?
The full code I provided below will allocate one instance of the Object class manually. If I want to instantiate the class whenever I want using a constructor function, do I need to move my object onto the stack and how would that be done? using .bss I can name my instance (for example test_object) but I'm not sure if I can name a stack address.
Full code so you can understand what I'm talking about: (GNU as, Linux x64)
.data
msg: .asciz "Hello world!\n"
.set msglen, . - msg
# CLASS struct
# This class struct only hold pointers to functions available for the class
.struct 0
Object:
# Class variables
Object.data:
.struct Object + 8
# Class pointers
Object.func_pointer:
.struct Object.data + 8
Object_size = . - Object
# Allocate Object_size bytes in the bss section to store the object instance
.bss
test_object:
.space Object_size
#----------------------------------------------------------------------------
# Code starts here
.text
#----------------------------------------------------------------------------
# Simple hello world function used as the target
hellofunc:
push %rbp
mov %rsp, %rbp
mov $1, %rax
mov $1, %rdi
mov $msg, %rsi
mov $msglen, %rdx
syscall
leave
ret
# Initiate the Object class by:
# Allocate a chunk of Object_size bytes on the stack
# Load value given in %rdi into Object.data
# Load the address of hellofunc into Object.func_pointer
initiate:
# Prologue
push %rbp
mov %rsp, %rbp
# Make %rdx point at the current object instance
mov $test_object, %rdx
# Load hellofunc address onto test_object.func_pointer
mov $hellofunc, %rax
mov %rax, Object.func_pointer(%rdx)
# Load data from %rdi onto test_object.data
mov %rdi, Object.data(%rdx)
# Test call to see if test_object.func_pointer is properly loaded
call *Object.func_pointer(%rdx)
# Epilogue
leave
ret
#---------------------------------------------------------------------------
# Main function
.globl _start
#---------------------------------------------------------------------------
_start:
mov $0xDEADBEEF, %rdi
call initiate
# return(0);
mov $60, %rax
mov $0, %rdi
syscall
I'm pretty sure all you're ever going to get out of any assembly language struct syntax is symbolic names for offsets, and a way to define them using the same .space directives that you'd normally use to reserve space for one static instance of a struct in the BSS. That's what NASM gives you, for example, and GAS's is even more rudimentary than that.
So yes, it's like a struct foo {int x; char c;}; definition in C: you use syntax that looks like declaring (reserving space for) global variables, but instead you're just defining the layout of a struct. (Except in GAS, you can only use .space and similar directives that can't take a value, no distinguishing one int from an array of 4 chars for example.)
But in GAS, it's so primitive that yes, it's just one way to
separately set a bunch of assemble-time constants with names like Object.func_pointer. You could do exactly the same thing with Object.func_pointer = 8, as well.
What is the difference between using: (.set) and (.struct)
Nothing. That's all it's doing for you. There isn't anything like a concept of a struct object, it's just one part of the tools that you can use to get symbolic names for offsets. They chose to call it .struct because that's one use-case.
However, you're repeating yourself unnecessarily by using .struct repeatedly (the example in the GAS manual does this, too; I don't know why). AFAIK you do have to repeat the struct name in each label (because GAS .struct syntax isn't very sophisticated), but you can use .space instead of having to name the previous field.
.struct 0
Object:
# .space 4
Object.obdata:
.space 8
Object.func_pointer:
.space 8
Object_size = . - Object
.text
mov $Object.obdata, %eax
mov $Object.func_pointer, %ecx
gcc -c foo.s && objdump -drwC -Mintel foo.o
...
0: b8 00 00 00 00 mov eax,0x0
5: b9 08 00 00 00 mov ecx,0x8
The names you choose to define after switching to the absolute section are 100% up to you, and not associated with any overall name for the struct.
NASM's struct support is a bit more sophisticated: you can define a layout in one spot, and use those member names when statically initializing an instance of it (e.g. in the .data section). Nasm - access struct elements by value and by address has an example. Note that it involves endstruc and iend directives, because you are actually defining a struct with members, not just separately setting a bunch of assemble-time constants with names like Object.func_pointer
Anything else like "constructors" you'll have to do yourself. e.g. writing the members into memory somewhere that you've decided is now an instance of a struct object.
This is assembly language, there is no compiler, any instructions you want in the final machine code you're going to have to write explicitly. (Unless you were using MASM, which magically adds instructions to your code in a few cases. GAS certainly doesn't; it was primarily designed to compiler compiler-generated asm. Deciding to emit instructions for a "constructor" at a certain point is something a compiler does internally, not via any special asm syntax. Same for hand-written asm.)

"Segmentation fault", x86_64 assembly, AT&T syntax

I am running my code in a 64-bit Linux environment where the Linux Kernel is built with IA32_EMULATION and X86_X32 disabled.
In the book Programming from the Ground Up the very first program doesn't do anything except produce a segfault:
.section .data
.section .text
.globl _start
_start:
movl $1, %eax
movl $0, %ebx
int $0x80
I convert the code to use x86-64 instructions but it also segfaults:
.section .data
.section .text
.globl _start
_start:
movq $1, %rax
movq $0, %rbx
int $0x80
I assembled both these programs like this:
as exit.s -o exit.o
ld exit.o -o exit
Running ./exit gives Segmentation fault for both. What am I doing wrong?
P.S. I have seen a lot of tutorials assembling code with gcc, however I'd like to use gas.
Update
Combining comments and the answer, here's the final version of the code:
.section .data
.section .text
.globl _start
_start:
movq $60, %rax
xor %rbx, %rbx
syscall
int $0x80 is the 32bit ABI. On normal kernels (compiled with IA32 emulation), it's available in 64bit processes, but you shouldn't use it because it only supports 32bit pointers, and some structs have a different layout.
See the x86 tag wiki for info on making 64bit Linux system calls. (Also ZX485's answer on this question). There are many differences, including the fact that the syscall instruction clobbers %rcx and %r11, unlike the int $0x80 ABI.
In a kernel without IA32 emulation, like yours, running int $0x80 is probably the same as running any other invalid software interrupt, like int $0x79. Single-stepping that instruction in gdb (on my 64bit 4.2 kernel that does include IA32 emulation) results in a segfault on that instruction.
It doesn't return and keep executing garbage bytes as instructions (which would also result in a SIGSEGV or SIGILL), or keep executing until it jumped to (or reached normally) an unmapped page. If it did, that would be the mechanism for segfaulting.
You can run a process under strace, e.g. strace /bin/true --version to make sure it's making the system calls you thought it would. You can also use gdb to see where a program segfaults. Using a debugger is essential, moreso than in most languages, because the failure mode in asm is usually just a segfault.
The first observation is that the code in both your examples effectively do the same thing, but are encoded differently. The site x86-64.org has some good information for those starting out with x86-64 development. The first code snippet that uses 32-bit registers is equivalent to the second because of Implicit Zero Extend:
Implicit zero extend
Results of 32-bit operations are implicitly zero extended to 64-bit values. This differs from 16 and 8 bit operations, that don't affect the upper part of registers. This can be used for code size optimisations in some cases, such as:
movl $1, %eax # one byte shorter movq $1, %rax
xorq %rax, %rax # three byte equivalent of mov $0,%rax
andl $5, %eax # equivalent for andq $5, %eax
The question is, why does this code segfault? If you had run this code on a typical x86-64 Linux distro your code may have exited as expected without generating a segfault. The reason that your code is failing is because you are using a custom kernel with IA32 emulation off.
IA32 emulation in the Linux kernel does allow you to use the 32-bit int 0x80 interrupt to make calls using the traditional 32-bit system call mechanism. This is an emulation layer, and doesn't support passing pointers that can't be represented in a 32-bit register. This is the case for stack based pointers since they fall outside the 4gb address space, and can't be accessed with 32-bit pointers.
Your system has IA32 emulation off, and because of that int 0x80 doesn't exist for backwards compatibility. The result is that the int 0x80 interrupt will throw a segmentation fault and your application will fail.
In x86-64 code it is preferred that you use the syscall instruction to make system calls to the 64-bit Linux kernel. This mechanism supports 64-bit operands and pointers where necessary. Ryan Chapman's site has some good information on the 64-bit SYSCALL interface which differs considerably from the 32-bit int 0x80 mechanism.
Your code could have been written this way to work in a 64-bit environment without IA32 emulation:
.section .text
.globl _start
_start:
mov $60, %eax
xor %ebx, %ebx
syscall
Other useful information on doing 64-bit development can be found in the 64-bit System V ABI. This document also better describes the general syscall convention used by the Linux kernel including side effects in Section A.2 . This document is also very informative if you also wish to interface with third party libraries and modules (like the C library etc).
The reason is that the Linux System Call Table for x86_64 is different from the table for x86.
In x86, SYS_EXIT is 1. In x64, SYS_EXIT is 60 and 1 is the value for SYS_WRITE, which, if called, expects a const char *buf in %RSI. If that buffer pointer is invalid, it probably segfaults.
%rax System call %rdi %rsi %rdx %r10 %r8 %r9
1 sys_write unsigned int fd const char *buf size_t
60 sys_exit int error_code

Linux sbrk() as a syscall in assembly

So, as a challenge, and for performance, I'm writing a simple server in assembly. The only way I know of is via system calls. (through int 0x80) Obviously, I'm going to need more memory than allocated at assemble, or at load, so I read up and decided I wanted to use sbrk(), mainly because I don't understand mmap() :p
At any rate, Linux provides no interrupt for sbrk(), only brk().
So... how do I find the current program break to use brk()? I thought about using getrlimit(), but I don't know how to get a resource (the process id I'd guess) to pass to getrlimit(). Or should I find some other way to implement sbrk()?
The sbrk function can be implemented by getting the current value and subtracting the desired amount manually. Some systems allow you to get the current value with brk(0), others keep track of it in a variable [which is initialized with the address of _end, which is set up by the linker to point to the initial break value].
This is a very platform-specific thing, so YMMV.
EDIT: On linux:
However, the actual Linux system call returns the new program break on success. On failure, the system call returns the current break. The glibc wrapper function does some work (i.e., checks whether the new break is less than addr) to provide the 0 and -1 return values described above.
So from assembly, you can call it with an absurd value like 0 or -1 to get the current value.
Be aware that you cannot "free" memory allocated via brk - you may want to just link in a malloc function written in C. Calling C functions from assembly isn't hard.
Source:
#include <unistd.h>
#define SOME_NUMBER 8
int main() {
void *ptr = sbrk(8);
return 0;
}
Compile using with Assembly Output option
gcc -S -o test.S test.c
Then look at the ASM code
_main:
Leh_func_begin1:
pushq %rbp
Ltmp0:
movq %rsp, %rbp
Ltmp1:
subq $16, %rsp
Ltmp2:
movl $8, %eax
movl %eax, %edi
callq _sbrk
movq %rax, -16(%rbp)
movl $0, -8(%rbp)
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
movl -4(%rbp), %eax
addq $16, %rsp
popq %rbp
ret
Leh_func_end1:
There is no system call for it but you should be able to still make the call

Conditional move problem

Code fragment from Assembly exercise (GNU Assembler, Linux 32 bit)
.data
more:
.asciz "more\n"
.text
...
movl $more, %eax # this is compiled
cmova more, %eax # this is compiled
cmova $more, %eax # this is not compiled
Error: suffix or operands invalid for `cmova'
I can place string address to %eax using movl, but cmova is not compiled. I need the source operand to be $more and not more, to use it for printing. Finally, this value goes to %ecx register of Linux system call 4 (write).
The assembler is correct! The CMOVcc instructions are more limited than MOV: they can only move 16/32/64-bit values from memory into a register, or from one register to another. They don't support immediate (or 8-bit register) operands.
(Reference: http://www.intel.com/Assets/PDF/manual/253666.pdf - from the set of manuals available at http://www.intel.com/products/processor/manuals/index.htm .)

How to manipulate strings with x86 assembly?

I'm in the process of writing an assembly program that takes two strings as input and concatenates them. Here's what I have: (using NASM syntax)
SECTION .data
hello: db "Hello ",0
world: db "world!",0
SECTION .text
; do the concatenation
Since I've never done any work with strings in x86 assembly before, I need to know how storing and manipulating strings work in the first place.
I'm guessing that once the length of each string is known, that concatenating would simply involve moving chunks of memory around. This part can be simplified by using libc. (I can use strlen() and strcat().)
My real problem is that I'm not familiar with the way strings are stored in x86 assembly. Do they just get added to the stack...? Do they go on a heap somewhere? Should I use malloc() (somehow)?
The strings in your example are stored the same way a global character array would be stored by a C program. They're just a series of bytes in the data section of your executable. If you want to concatenate them, you're going to need some space to do it - either do it on the stack, or call malloc() to get yourself some memory. As you say, you can just use strcat() if you are willing to call out to libc. Here's a quick example I made (AT&T syntax), using a global buffer to concatenate the strings, then print them out:
.data
hello:
.asciz "Hello "
world:
.asciz "world!"
buffer:
.space 100
.text
.globl _main
.globl _puts
.globl _strcat
_main:
push %rbp
mov %rsp, %rbp
leaq buffer(%rip), %rdi
leaq hello(%rip), %rsi
callq _strcat
leaq buffer(%rip), %rdi
leaq world(%rip), %rsi
callq _strcat
leaq buffer(%rip), %rdi
callq _puts
mov $0, %rax
pop %rbp
retq

Resources