I tried to use gdb to debug the Assemble code but got error message,it said:
(gdb) run Starting program: /root/assembler_program/bsawp.o
/bin/bash: /root/assembler_program/bsawp.o: cannot execute binary file
The code:
.section .text
.globl _start
_start:
nop
movl 0x12345678 , %ebx
bswap %ebx
movl $1 , %eax
int $0x80
Then I use gdb :
(gdb) break *_start+1
Breakpoint 1 at 0x400079
(gdb) run
Starting program: /root/assembler_program/bsawp
Breakpoint 1, 0x0000000000400079 in _start ()
(gdb) step
Single stepping until exit from function _start,
which has no line number information.
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400079 in _start ()
Could you please provide any hint and suggestion?
Thanks!
Best regards
Here:
Starting program: /root/assembler_program/bsawp.o
you are trying to run a relocatable object file. Don't do that.
You must link your object into an executable first. Something like this:
gcc -nostdlib -nostartfile test.s
Here:
Starting program: /root/assembler_program/bsawp
you apparently did link the bsap.o into an executable. The crash is happening here:
(gdb) x/i $pc
=> 0x400079 <_start+1>: mov 0x12345678,%ebx
This instruction is trying to load value from address 0x12345678, into register. But that address does not point to a valid memory location.
You most likely meant for it to load a constant 0x12345678, in which case the instruction you want is:
movl $0x12345678, %ebx
With that fix, I get expected:
(gdb) run
Starting program: /tmp/a.out
[Inferior 1 (process 238270) exited with code 022]
(gdb) p/x 022
$1 = 0x12
Related
I have been having some issues debugging code assembled by nasm with gdb: it seems like gdb doesn't do well with nasm local labels. nasm generates a local symbol named «function».label, which seems to confuse gdb, as it loses track of which function it is in.
Here is one scenario in which it gives a sub-optimal debugging experience:
section .text
global _start
_start:
call foo
ud2
foo:
push rbp
mov rbp, rsp
call bar
.end:
pop rbp
ret
bar:
ret
Compile and debug:
$ nasm -f elf64 -g -F DWARF example.asm -o example.o
$ ld example.o -o example
$ gdb ./example
Reading symbols from ./example...done.
(gdb) b foo
Breakpoint 1 at 0x400087: file example.asm, line 10.
(gdb) run
Starting program: /home/mvanotti/orga2/gdb/example
Breakpoint 1, foo () at example.asm:10
10 push rbp
(gdb) ni
11 mov rbp, rsp
(gdb) ni
12 call bar
(gdb) ni
Program received signal SIGILL, Illegal instruction.
_start () at example.asm:7
7 ud2
As you can see, nexti continues execution even after the return from the bar function call. I believe this is caused because the next instruction in foo belongs to the foo.end symbol, causing gdb to not recognize that as the return point of the function. Adding any other instruction before the .end label in the asm file fixes the issue.
Similarly, the backtrace gets all messed up when it steps into a local label:
(gdb)
foo.end () at example.asm:14
14 pop rbp
(gdb) bt
#0 foo.end () at example.asm:14
#1 0x0000000000000000 in ?? ()
(gdb)
This also affects yasm and lldb.
There is not a clear workaround for this. I couldn't find an option in nasm to not emit the function.label symbols, or an easy way to remove them. strip for example, lets you specify the --wildcard option, but the regexp syntax is too basic and cannot match something like .+\.*. The closest I got was strip --wildcard -N "*.*", but that also matches .something
In gas, this is solved by creating a label in the form of .Llocal_label$ which gets discarded automatically by ld.
I'm trying to make JonesForth run on a recent MacBook out of the box, just using Mac tools.
I started to convert everything 64 bits and attend to the Mac assembler syntax.
I got things to assemble, but I immediately run into a curious segmentation fault:
/* NEXT macro. */
.macro NEXT
lodsq
jmpq *(%rax)
.endm
...
/* Assembler entry point. */
.text
.globl start
.balign 16
start:
cld
mov %rsp,var_SZ(%rip) // Save the initial data stack pointer in FORTH variable S0.
mov return_stack_top(%rip),%rbp // Initialise the return stack.
//call set_up_data_segment
mov cold_start(%rip),%rsi // Initialise interpreter.
NEXT // Run interpreter!
.const
cold_start: // High-level code without a codeword.
.quad QUIT
QUIT is defined like this via macro defword:
.macro defword
.const_data
.balign 8
.globl name_$3
name_$3 :
.quad $4 // Link
.byte $2+$1 // Flags + length byte
.ascii $0 // The name
.balign 8 // Padding to next four-byte boundary
.globl $3
$3 :
.quad DOCOL // Codeword - the interpreter
// list of word pointers follow
.endm
// QUIT must not return (ie. must not call EXIT).
defword "QUIT",4,,QUIT,name_TELL
.quad RZ,RSPSTORE // R0 RSP!, clear the return stack
.quad INTERPRET // Interpret the next word
.quad BRANCH,-16 // And loop (indefinitely)
...more code
When I run this, I get a segmentation fault the first time in the NEXT macro:
(lldb) run
There is a running process, kill it and restart?: [Y/n] y
Process 83000 exited with status = 9 (0x00000009)
Process 83042 launched: '/Users/klapauciusisgreat/jonesforth64/jonesforth' (x86_64)
Process 83042 stopped
* thread #1, stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x0000000100000698 jonesforth`start + 24
jonesforth`start:
-> 0x100000698 <+24>: jmpq *(%rax)
0x10000069a <+26>: nopw (%rax,%rax)
jonesforth`code_DROP:
0x1000006a0 <+0>: popq %rax
0x1000006a1 <+1>: lodsq (%rsi), %rax
Target 0: (jonesforth) stopped.
rax does point to what I think is the dereferenced address, DOCOL:
(lldb) register read
General Purpose Registers:
rax = 0x0000000100000660 jonesforth`DOCOL
So one mystery is:
Why does RAX point to DOCOL instead of QUIT? My guess is that the instruction was halfway executed and the result of the indirection was stored in rax. What are some good pointers to documentation?
Why the segmentation fault?
I commented out the original segment setup code in the original that called brk to set up a data segment. Another [implementation] also did not call it at all, so I thought I could as well ignore this. Is there any magic on how to set up segment permissions with syscalls in a 64-bit binary on Catalina? The make command is pretty much the standard JonesForth one:
jonesforth: jonesforth.S
gcc -nostdlib -g -static $(BUILD_ID_NONE) -o $# $<
P.S.: Yes, I can get JonesForth to work perfectly in Docker images, but that's besides the point. I really want it to work in 64 bit on Catalina, out of the box.
The original code had something like
mov $cold_start,%rsi
And the Apple assembler complains about not being able to use 32 immediate addressing in 64-bit binaries.
So I tried
mov $cold_start(%rip),%rsi
but that also doesn't work.
So I tried
mov cold_start(%rip),%rsi
which assembles, but of course it dereferences cold start, which is not something I need.
The correct way of doing this is apparently
lea cold_start(%rip),%rsi
This seems to work as intended.
I'm trying to compile the piece of assembly code below using gcc. I have finally got it to the point that it compiles an object file, but when I try and run it it get an error back saying 'cannot execute binary file'. I am on windows 10 version 1511.
I am using the msys terminal and compiling by entering
gcc -c main.s -o main.o
I try and execute the file by entering
./main.o
And I get back the error
./main.o: ./main.o: cannot execute binary file
The assembly code is:
.section .text
.global main
main:
mov $4,%eax
mov $1,%ebx
mov $message,%ecx
mov msglength,%edx
int $0x80
mov $1, %eax
mov $0, %ebx
int $0x80
.section .data
message: .ascii "Hello world!"
msglength: .word 12
Any help would be much appreciated.
That is a Linux program and will not work on Windows.
As described in the comments, you need to link the program, remove -c from the gcc command line.
The book Assembly Language Step by Step provides the following code as a sandbox:
section .data
section .text
global _start
_start:
nop
//insert sandbox code here
nop
Any example that I include in the space for sandbox is creating a segmentation fault. For example, adding this code:
mov ax, 067FEh
mov bx, ax
mov cl, bh
mov ch, bl
Then compiling with:
nasm -f macho sandbox.asm
ld -o sandbox -e _start sandbox.o
creates a seg fault when I run it on my OS/X. Is there a way to get more information about what's causing the segmentation fault?
The problem you have is that you have created a program that runs past the end of the code that you have written.
When your program executes, the loader will end up issuing a jmp to your _start. Your code then runs, but you do not have anything to return to the OS at the end, so it will simply continue running, executing whatever bytes happen to be in RAM after your code.
The simplest fix would be to properly exit the code. For example:
mov eax, 0x1 ; system call number for exit
sub esp, 4 ; OS X system calls needs "extra space" on stack
int 0x80
Since you are not generating any actual output, you would need to step through with a debugger to see what's going on. After compiling you could use lldb to step through.
lldb ./sandbox
image dump sections
Make note of the address listed that is of type code for your executable (not dyld). It will likely be 0x0000000000001fe6. Continuing within lldb:
b s -a 0x0000000000001fe6
run
register read
step
register read
step
register read
At this point you should be past the NOPs and see things changing in registers. Have fun!
I'm trying to debug an assembly program using gdb and Emacs. My problem is that, when I try to debug step-by-step, it doesn't show a pointer arrow at the current executing line. The code I'm trying to debug is:
SECTION .data ; Section containing initialised data
EatMsg: db "Eat at Joe's!",10
EatLen: equ $-EatMsg
SECTION .bss ; Section containing uninitialized data
SECTION .text ; Section containing code
global _start ; Linker needs this to find the entry point!
_start:
nop ; This no-op keeps gdb happy...
mov eax,4 ; Specify sys_write call
mov ebx,1 ; Specify File Descriptor 1: Standard Output
mov ecx,EatMsg ; Pass offset of the message
mov edx,EatLen ; Pass the length of the message
int 80H ; Make kernel call
MOV eax,1 ; Code for Exit Syscall
mov ebx,0 ; Return a code of zero
int 80H ; Make kernel call
and I'm compiling with these lines:
nasm -f elf -g -F stabs eatsyscall.asm -l eatsyscall.lst
ld -melf_i386 -o eatsyscall eatsyscall.o
What I see in Emacs is that. In this screenshot I'm currently executing the line after the breakpoint and no pointer to that line appears. Is it possible to have one?
first of all, i hope you are still looking for the solution, it has been 2 years ! if you are, then try coaxing nasm to generate debugging information with DWARF instead of STAB i.e the following
nasm -f elf -g -F dwarf eatsyscall.asm ...
that seems to work for me (TM)
Try to download nasm2.5 or the latest available, it should work