How to debug an assembled program? - debugging

I have a program written in assembly that crashes with a segmentation fault. (The code is irrelevant, but is here.)
My question is how to debug an assembly language program with GDB?
When I try running it in GDB and perform a backtrace, I get no meaningful information. (Just hex offsets.)
How can I debug the program?
(I'm using NASM on Ubuntu, by the way if that somehow helps.)

I would just load it directly into gdb and step through it instruction by instruction, monitoring all registers and memory contents as you go.
I'm sure I'm not telling you anything you don't know there but the program seems simple enough to warrant this sort of approach. I would leave fancy debugging tricks like backtracking (and even breakpoints) for more complex code.
As to the specific problem (code paraphrased below):
extern printf
SECTION .data
format: db "%d",0
SECTION .bss
v_0: resb 4
SECTION .text
global main
main:
push 5
pop eax
mov [v_0], eax
mov eax, v_0
push eax
call printf
You appear to be just pushing 5 on to the stack followed by the address of that 5 in memory (v_0). I'm pretty certain you're going to need to push the address of the format string at some point if you want to call printf. It's not going to take to kindly to being given a rogue format string.
It's likely that your:
mov eax, v_0
should be:
mov eax, format
and I'm assuming that there's more code after that call to printf that you just left off as unimportant (otherwise you'll be going off to never-never land when it returns).

You should still be able to assemble with Stabs markers when linking code (with gcc).
I reccomend using YASM and assembling with -dstabs options:
$ yasm -felf64 -mamd64 -dstabs file.asm
This is how I assemble my assembly programs.
NASM and YASM code is interchangable for the most part (YASM has some extensions that aren't available in NASM, but every NASM code is well assembled with YASM).
I use gcc to link my assembled object files together or while compiling with C or C++ code. When using gcc, I use -gstabs+ to compile it with debug markers.

Related

mul eax with declared .data value in NASM assembly

I'm a total beginner at Assembly and i have been trying to get the basics in NASM. Im on a mac, using xcode and i have started dealing with data and i have a simple question.
I have had a hard time finding the answer and the manual for NASM is very overwhelming.
This must be super basic for you NASM guru's out there.
if i declare a variable out in memory
section .data
counter dw 0
global _start
_start:
inc counter ; i get a "invalid combination of opcode and operands" here
ret
Is it so that i must move the memory into a register to perform operations on it, and i can't manipulate memory "in place"?
Im sorry if this is a silly question, but i have tried googling this and couldn't find a clear straight up answer.
In NASM (unlike MASM) a bare symbol is an immediate value. For a memory reference enclose it in square brackets and indicate the required size.
inc word [counter]

Why does gcc emit 0x0(%r13) in one instruction but (%r13) in another?

I am debugging a piece of code which has the following instruction.
mov %esi,0x0(%r13)
Then at another place, I see an instruction like this:
mov %esi,(%r13)
I thought the former one moves the contents of esi register to address given by contents of r13 + 0x0. With that logic, the latter should also result in the same effect.
Is there any difference between these instructions?
Why does gcc write the same thing differently?
EDIT: The disassembly has been generated using objdump -S.

How can I print numbers in my assembly program

I have a problem with my assembly program. My assembly compiler is NASM. The source and the outputs are in this picture:
The problem is that I can't print numbers from calculations with the extern C function printf(). How can I do it?
The output should be "Ergebnis: 8" but it isn't correct.
In NASM documentation it is pointed that NASM Requires Square Brackets For Memory References. When you write label name without bracket NASM gives its memory address (or offset as it is called sometimes). So, mov eax, val_1 it means that eax register gets val_1's offset. When you add eax, val_2, val_2 offset is added to val_1 offset and you get the result you see.
Write instead:
mov eax, [val_1]
add eax, [val_2]
And you shoul get 8 in eax.
P.S. It seems that you have just switched to NASM from MASM or TASM.
There are a lot of guides for switchers like you. See for example nice tutorials here and here.

implementation of .cfi_remember_state

I was wondering how exactly .cfi_remember_state is implemented. I know it is a pseudo-op, so I suppose it is converted into a couple of instructions when assembling. I am interested what exact instructions are used to implement it. I tried many ways to figure it out. Namely:
Read GAS source code. But failed to find anything useful enough.
Read GAS documentation. But the .cfi_remember_state entry is just a simple joke (literally).
Tried to find a gcc switch that would make gcc generate asm from C code with pseudo-ops "expanded". Failed to find such a switch for x86 / x86-64. (Would be nice if someone could point me to such a switch, assuming it exists, BTW.)
Google-fu && searching on SO did not yield anything useful.
The only other solution in my mind would be to read the binary of an assembled executable file and try to deduce the instructions. Yet I would like to avoid such a daunting task.
Could any of You, who knows, enlighten me, how exactly it is implemented on x86 and/or x86-64? Maybe along with sharing how / where that information was acquired, so I could check other pseudo-ops, if I ever have the need to?
This directive is a part of DWARF information (really all it does is emit DW_CFA_remember_state directive). Excerpt from DWARF3 standard:
The DW_CFA_remember_state instruction takes no operands. The required
action is to push the set of rules for every register onto an implicit
stack.
You may play with DWARF information using objdump. Lets begin with simple void assembler file:
.text
.globl main
.type main, #function
main:
.LFB0:
.cfi_startproc
#.cfi_remember_state
.cfi_endproc
.LFE0:
.size main, .-main
Compile it with gcc cfirem.s -c -o cfirem.o
Now disassemble generated DWARF section with objdump --dwarf cfirem.o
You will get:
00000018 00000014 0000001c FDE cie=00000000 pc=00000000..00000000
DW_CFA_nop
DW_CFA_nop
...
If you will uncomment .cfi_remember_state, you will see instead:
00000018 00000014 0000001c FDE cie=00000000 pc=00000000..00000000
DW_CFA_remember_state
DW_CFA_nop
DW_CFA_nop
...
So it is not really converting in assembler instructions (try objdump -d to see that there are no assembler instructions in our sample at all). It is converted in DWARF pseudo-instructions, that are used when debugger like GDB processes your variable locations, stack information and so on.

Force GCC to push arguments on the stack before calling function (using PUSH instruction)

I have started developing a small 16-bit OS under GCC/G++.
I am using a GCC cross-compiler, which I compiled under Cygwin, I am putting asm(".code16gcc\n") as the first line of each .CPP file, using Intel ASM syntax and the command lines for compiling and linking a .CPP file look like this:
G++: i586-elf-g++ -c $(CPP_FILE) -o $(OBJECT_OUTPUT) -nostdinc -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fpermissive -masm=intel
LD: i586-elf-ld -T $(LD_SCRIPT) $(OBJECT_OUTPUT) -o $(BINARY_OUTPUT)
The problem I am currently facing is the way GCC translates function-calling code into assembly.
To be more specific, instead of using the PUSH instruction to pass the arguments, GCC "calculates" the offsets relative to ESP the arguments should be located at, and then uses the MOV instruction to write the stack manually.
This is not beneficial for me, since I rely on the PUSH instruction in my assembly code. To illustrate my problem clearer, take these 2 functions:
void f2(int x);
void f1(){
int arg = 8;
asm("mov eax, 5"); // note: super hacky unsafe use of GNU C inline asm
asm("push eax"); // Writing registers without declaring a clobber is UB
f2(arg);
asm("pop eax");
}
void f2(int x){
}
In function f1, I am saving EAX using the PUSH instruction, and I would expect to have it restored to 5 after calling f2 and executing the "POP EAX" instruction. It turns out however that EAX becomes 8, not 5. That's because the ASSEMBLY CODE GCC generates looks like this (I've included the source as well for clarity):
void f1()
C++: {
push ebp
mov ebp,esp
sub esp,byte +0x14
C++: int arg = 8;
mov dword [ebp-0x4],0x8
C++: asm("mov eax, 5");
mov eax,0x5
C++: asm("push eax");
push eax
C++: f2(arg);
mov eax,[ebp-0x4]
mov [dword esp],eax =======>>>>>> HERE'S THE PROBLEM, WHY NOT 'PUSH EAX' ?!!
call f2
C++: asm("pop eax");
pop eax
C++: }
o32 leave
o32 ret
void f2(int x)
C++: {
push ebp
mov ebp,esp
C++: }
pop ebp
o32 ret
I have tried using some G++ compilation flags like -mpush-args or -mno-push-args and another one which I can't remember and GCC still doesn't want to use PUSH. The version I'm using is i586-elf-g++ (GCC) 4.7.2 (Cross-Compiler recompiled in Cygwin).
Thank you in advance!
UPDATE: Here's a webpage I've found: http://fixunix.com/linux/6799-gcc-function-call-pass-arguments-via-push.html
That just seems really stupid for GCC to do, considering that it limits the usability of inline assembly for complex stuff. :( Please leave an answer if you have a suggestion.
I've been very lucky finding a solution to this problem, but it finally does what I want it to do.
Here's what the GCC manual for version 4.7.2 state:
-mpush-args
-mno-push-args
Use PUSH operations to store outgoing parameters. This method is shorter
and usually equally fast as method using SUB/MOV operations and is enabled
by default. In some cases disabling it may improve performance because of
improved scheduling and reduced dependencies.
-maccumulate-outgoing-args
If enabled, the maximum amount of space required for outgoing arguments will
be computed in the function prologue. This is faster on most modern CPUs
because of reduced dependencies, improved scheduling and reduced stack usage
when preferred stack boundary is not equal to 2. The drawback is a notable
increase in code size. This switch implies ‘-mno-push-args’.
I'm saying I am lucky because -mpush-args does not work, what works is instead "-mno-accumulate-outgoing-args", which is not even documented!
I had similar question lately and people didn't find it important I guess, I found out undocumented option at least for GCC 4.8.1, don't know about latest 4.9 version.
Someone said he gets the "warning: stack probing requires -maccumulate-outgoing-args for correctness [enabled by default]" error message.
To disable stack probing, use -mno-stack-arg-probe, so pass these options I guess to ensure:
-mpush-args -mno-accumulate-outgoing-args -mno-stack-arg-probe
For me this works now, it uses PUSH, much smaller and better code, and much easier to debug with OllyDbg.

Resources