I'm playing with GAS assembly and linking it without using gcc. Instead I'm using the as assembler and linking with ld.
My code:
.section .text
.globl _start
_start:
xorq %rax, %rax
movb $60, %al
movb $1, %dil
int $0x80
The command I use to assemble and link:
as -g -D -o test.o test.S && ld --format elf64-x86-64 -o test test.o
And this is the gdb debugging before/after:
(gdb) disas _start
Dump of assembler code for function _start:
0x0000000000400078 <+0>: xor %rax,%rax
0x000000000040007b <+3>: mov $0x3c,%al
0x000000000040007d <+5>: mov $0x1,%dil
0x0000000000400080 <+8>: int $0x80
End of assembler dump.
(gdb) b *_start+8
Breakpoint 1 at 0x400080: file test.S, line 7.
(gdb) r
Starting program: /tmp/test
Breakpoint 1, _start () at test.S:7
7 int $0x80
(gdb) i r
rax 0x3c 60
rbx 0x0 0
rcx 0x0 0
rdx 0x0 0
rsi 0x0 0
rdi 0x1 1
rbp 0x0 0x0
rsp 0x7fffffffebc0 0x7fffffffebc0
r8 0x0 0
r9 0x0 0
r10 0x0 0
r11 0x0 0
r12 0x0 0
r13 0x0 0
r14 0x0 0
r15 0x0 0
rip 0x400080 0x400080 <_start+8>
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400082 in ?? ()
(gdb) i r
rax 0x12 18
rbx 0x0 0
rcx 0x0 0
rdx 0x0 0
rsi 0x0 0
rdi 0x1 1
rbp 0x0 0x0
rsp 0x7fffffffebc0 0x7fffffffebc0
r8 0x0 0
r9 0x0 0
r10 0x0 0
r11 0x0 0
r12 0x0 0
r13 0x0 0
r14 0x0 0
r15 0x0 0
rip 0x400082 0x400082
eflags 0x10246 [ PF ZF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) x/x $rip
0x400082: 0x00000000
(gdb) x/x $rip-2
0x400080 <_start+8>: 0x000080cd
%rip is continuing with his trip through the code to 0x40082 where no code exists. Any idea how can I avoid the SEGFAULT after executing exit() syscall?
Add
Stracing the program:
$ strace ./test
execve("./test", ["./test"], [/* 18 vars */]) = 0
exit(1) = 18
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x12} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
Related
The assembly file is obtained by using gcc -g -S, and the part of .s file is as follows:
.L3:
.loc 1 22 11
mov eax, DWORD PTR -12[rbp]
mov edx, eax
mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
call _ZNSolsEi
.loc 1 22 18
mov rdx, QWORD PTR .refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_[rip]
mov rcx, rax
call _ZNSolsEPFRSoS_E
.loc 1 23 7
mov DWORD PTR -12[rbp], 0
.loc 1 12 2
add DWORD PTR -4[rbp], 1
jmp .L6
What does .loc 1 22 11 stand for?
When the -g flag is added to gcc it directs the compiler to add debugging information. .loc appears only when the compiler generates debugging information with -g flag:
https://sourceware.org/binutils/docs-2.38/as/Loc.html#Loc
I'm using the qiling framework to emulate a snake game which runs fine in my x86 64 Windows environment, but it's failing in the emulated environment. It works fine run normally, but I'm having trouble getting a breakpoint to work in WinDbg at the place it's failing. My question is more about understanding my problem in WinDbg, but I'll provide the emulator logs for context:
[=] Initiate stack address at 0xfffdd000
[=] Loading snake.exe to 0x400000
[=] PE entry point at 0x4033ae
[=] TEB addr is 0x6000
[=] PEB addr is 0x6044
[=] Loading ../examples/rootfs/x8664_windows\Windows\System32\ntdll.dll ...
[!] Warnings while loading ../examples/rootfs/x8664_windows\Windows\System32\ntdll.dll:
[!] - SizeOfHeaders is smaller than AddressOfEntryPoint: this file cannot run under Windows 8.
[!] - AddressOfEntryPoint lies outside the sections' boundaries. AddressOfEntryPoint: 0x0
[=] Done with loading ../examples/rootfs/x8664_windows\Windows\System32\ntdll.dll
[=] Loading ../examples/rootfs/x8664_windows\Windows\System32\kernel32.dll ...
[=] Done with loading ../examples/rootfs/x8664_windows\Windows\System32\kernel32.dll
[=] Loading ../examples/rootfs/x8664_windows\Windows\System32\mscoree.dll ...
[=] Done with loading ../examples/rootfs/x8664_windows\Windows\System32\mscoree.dll
0x4033ae: jmp qword ptr [rip + 0x402000]
[!] api _CorExeMain is not implemented
This seems like a likely culprit, so I try to set a breakpoint at 0x4033ae in WinDbg with the command bu 0x4033ae. I also tried bp.
0x102bdbd1: push rbx
0x102bdbd3: sub esp, 0x20
0x102bdbd7: and dword ptr [rsp + 0x30], 0
0x102bdbdd: lea ecx, [rsp + 0x30]
0x102bdbe1: call 0x102b4548
0x102b4549: push rbx
0x102b454b: sub esp, 0x20
0x102b454e: mov eax, dword ptr [rip + 0x5b4dc]
[x] CPU Context:
[x] ah : 0xff
... snip ...
[x] gs : 0x78
[x] Hexdump:
[x] 8b 05 dc b4 05 00 48 8b
[x] Disassembly:
[=] 102b454e [mscoree.dll + 0x00154e] 8b 05 dc b4 05 00 48 8b d9 85 c0 75 05 e8 c4 fc ff ff 8b 05 ca b4 05 00 83 f8 02 75 0f 48 85 db 74 0a 48 8b 05 c9 b4 05 00 48 89 03 8b 05 b0 b4 05 00 48 83 c4 20 5b c3 cc cc cc cc cc cc cc ccmov eax, dword ptr [0x5b4dc]
> dec eax
> mov ebx, ecx
> test eax, eax
> jne 0x102b4560
> call 0x102b4224
> mov eax, dword ptr [0x5b4ca]
> cmp eax, 2
> jne 0x102b457a
> dec eax
> test ebx, ebx
> je 0x102b457a
> dec eax
> mov eax, dword ptr [0x5b4c9]
> dec eax
> mov dword ptr [ebx], eax
> mov eax, dword ptr [0x5b4b0]
> dec eax
> add esp, 0x20
> pop ebx
> ret
> int3
> int3
> int3
> int3
> int3
> int3
> int3
> int3
[x] PC = 0x102b454e (../examples/rootfs/x8664_windows\Windows\System32\mscoree.dll + 0x154e)
[=] Memory map:
[=] Start End Perm Label Image
[=] 00006000 - 0000c000 rwx [FS/GS]
[=] 00030000 - 00031000 rwx [GDT]
[=] 00400000 - 00408000 rwx [PE] snake.exe
[=] 05000000 - 05001000 rwx [heap]
[=] 06000000 - 0c000000 rwx [FS/GS]
[=] 10000000 - 101f5000 rwx ntdll.dll ../examples/rootfs/x8664_windows\Windows\System32\ntdll.dll
[=] 101f5000 - 102b3000 rwx kernel32.dll ../examples/rootfs/x8664_windows\Windows\System32\kernel32.dll
[=] 102b3000 - 10318000 rwx mscoree.dll ../examples/rootfs/x8664_windows\Windows\System32\mscoree.dll
[=] fffdd000 - ffffe000 rwx [stack]
Traceback (most recent call last):
... snip ...
File "C:\Users\jonat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\unicorn\unicorn.py", line 465, in emu_start
raise UcError(status)
unicorn.unicorn.UcError: Invalid memory mapping (UC_ERR_MAP)
In WinDbg, I get:
CommandLine: C:\Users\jonat\Documents\GitHub\synthesis\obfu\snake.exe
************* Path validation summary **************
Response Time (ms) Location
Deferred srv*
Symbol search path is: srv*
Executable search path is:
ModLoad: 00e60000 00e68000 ConsoleGraphics.exe
ModLoad: 770f0000 77293000 ntdll.dll
ModLoad: 74810000 74862000 C:\WINDOWS\SysWOW64\MSCOREE.DLL
ModLoad: 74fb0000 750a0000 C:\WINDOWS\SysWOW64\KERNEL32.dll
ModLoad: 75fa0000 761b5000 C:\WINDOWS\SysWOW64\KERNELBASE.dll
(9b8.7854): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=3c560000 edx=00000000 esi=77102054 edi=7710261c
eip=771a1ba2 esp=00fff9cc ebp=00fff9f8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2b:
771a1ba2 cc int 3
Which seems to be a standard breakpoint triggered by ntdll but by the time this is triggered, we have already passed the address 0x4033ae where I was trying to apply it. I realized that this is probably because the addressing scheme of the process seems to be mapped differently by the execution context within my OS / WinDbg and the qiling emulation. How can I begin debugging this problem, or at least finding the relevant breakpoint in WinDbg.
the query isn't exactly related to windbg
as I commented Qiling Framework hasn't yet implemented dotnet and needs someone to contribute the implementation
since this query has a windbg tag and a debugging tag too and
I have been wanting to test the Qiling framework for sometime now on a windows machine
I took this query as an opportunity to do so
Qiling is built upon unicorn emulation framework
I have dabbled with unicorn and found it quiet useful
installed Qiling [pip3 install Qiling] on a x64 windows10 machine
windows documentation is quiet scarce and the one example disasm_x886_windows.py indicated in github repo is missing in the repo
had to scratch around to get a working setup
after installing Qiling it needs a virtual filesystem to operate upon with pertient windows dlls and registry hives
this is done by using the dllcollector.bat provided by in the repo
basically the collector.bat xcopies relevent 32 bit and 64 bit dlls and reg saves registry hives
f:\>md QILING
f:\>cd QILING
f:\QILING>ls
f:\QILING>f:\wget\wget.exe -c https://raw.githubusercontent.com/qilingframework/qiling/master/examples/scripts/dllscollector.bat
2021-11-14 03:03:05 (1.28 MB/s) - 'dllscollector.bat' saved [10085/10085]
f:\QILING>ls
dllscollector.bat
f:\QILING>file dllscollector.bat
dllscollector.bat: DOS batch file, ASCII text, with very long lines
f:\QILING>dllscollector.bat
Does F:\QILING\examples\rootfs\x8664_windows\Windows\registry\NTUSER.DAT specify a file name
or directory name on the target
(F = file, D = directory)? f
C:\Users\Default\NTUSER.DAT -> F:\QILING\examples\rootfs\x8664_windows\Windows\registry\NTUSER.DAT
1 File(s) copied
The operation completed successfully.
snip all copy and save operations
f:\QILING>ls
dllscollector.bat examples
now that we have collected the dlls lets copy two test binaries
one an x64 console app and
another a .net console binary and
write a python script to emulate them using QILING framework
f:\QILING>ls
dllscollector.bat examples
f:\QILING>md testqiling
f:\QILING>xcopy ..\tbins .\testqiling\
..\tbins\mcall.exe
..\tbins\printxcode.exe
..\tbins\qiliwin.py
3 File(s) copied
f:\QILING>cd testqiling
f:\QILING\testqiling>file *
mcall.exe: PE32+ executable (GUI) x86-64, for MS Windows
printxcode.exe: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows
qiliwin.py: Python script, ASCII text executable, with CRLF line terminators
f:\QILING\testqiling>printxcode.exe |head -n 2
HResult is 80070057 xcode is E0434352 Value does not fall within the expected range.
HResult is 80004003 xcode is E0434352 Value cannot be null.
f:\QILING\testqiling>start /wait mcall.exe
f:\QILING\testqiling>echo %errorlevel%
1677
the script as follows
the stop_on_exit_trap is added to avoid crashing of mcall.exe when it returns to crt from main() due to unreachable PC (0x0 as rip)
trace traces and prints all executed instructions
verbose provides some additional logs
f:\QILING\testqiling>cat qiliwin.py
import os
from qiling import *
from qiling.const import QL_VERBOSE
from qiling.extensions import trace
os.system('') #bug explotation to make ansi colors
rootfs = r"F:\QILING\examples\rootfs\x8664_windows"
bin2exec = [
r"F:\QILING\testqiling\mcall.exe",
r"F:\QILING\testqiling\printxcode.exe"
]
for binary in bin2exec:
print("executing binary\n=====================\n%s\n=====================\n" % binary);
ql = Qiling([binary],rootfs,verbose=QL_VERBOSE.DEBUG,stop_on_exit_trap=True)
trace.enable_full_trace(ql)
ql.run()
executing the script we get
qiling.exception.QlErrorFileNotFound: Cannot find dll in F:\QILING\examples\rootfs\x8664_windows\Windows\System32\mscoree.dll
copying the mscoree.dll from system32 to rootfs/system2 and checking it crashes again with unmapped error as pointed in query
lets open the .net binary in an x64 windbg and check
F:\QILING\testqiling>cdb -c "sxe ld:mscoree;g;q" printxcode.exe | awk /Reading/,/quit/
0:000> cdb: Reading initial command 'sxe ld:mscoree;g;q'
ModLoad: 00000000`77e30000 00000000`77e39000 C:\WINDOWS\System32\wow64cpu.dll
ModLoad: 00000000`73f90000 00000000`73fe2000 C:\WINDOWS\SysWOW64\MSCOREE.DLL
quit:
so this binary needs the mscoree from syswow
f:\QILING\testqiling>copy c:\Windows\SysWOW64\mscoree.dll F:\QILING\examples\rootfs\x8664_windows\Windows\System32\.
Overwrite F:\QILING\examples\rootfs\x8664_windows\Windows\System32\.\mscoree.dll? (Yes/No/All): y
1 file(s) copied.
Execution now doesnt crash
F:\QILING\testqiling>python qiliwin.py
executing binary
=====================
F:\QILING\testqiling\mcall.exe
=====================
[+] Profile: Default
[+] Windows Registry PATH: F:\QILING\examples\rootfs\x8664_windows\Windows\registry
[=] Initiate stack address at 0x7ffffffde000
[=] Loading F:\QILING\testqiling\mcall.exe to 0x140000000
[=] PE entry point at 0x140001030
[=] TEB addr is 0x6000030
[=] PEB addr is 0x60000b8
[=] Loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll ...
[!] Warnings while loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll:
[!] - SizeOfHeaders is smaller than AddressOfEntryPoint: this file cannot run under Windows 8.
[!] - AddressOfEntryPoint lies outside the sections' boundaries. AddressOfEntryPoint: 0x0
[+] DLL preferred base address: 0x180000000
[=] Done with loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll
[=] Loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\kernel32.dll ...
[+] DLL preferred base address: 0x180000000
[+] DLL preferred base address is taken, loading to: 0x1801f0000
[=] Done with loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\kernel32.dll
[+] Done with loading F:\QILING\testqiling\mcall.exe
[+] Setting up exit trap at 0x0x140004000
[+] 140001030 | 4883ec48 sub rsp, 0x48 | rsp = 0x0
[+] 140001034 | 41b803000000 mov r8d, 0x3 |
[+] 14000103a | ba02000000 mov edx, 0x2 |
[+] 14000103f | b901000000 mov ecx, 0x1 |
[+] 140001044 | e8b7ffffff call 0x140001000 | rsp = 0x0, rip = 0x0
[+] 140001000 | 4489442418 mov dword ptr [0x18], r8d | rsp = 0x0, r8d = 0x0
[+] 140001005 | 89542410 mov dword ptr [0x10], edx | rsp = 0x0, edx = 0x2
[+] 140001009 | 894c2408 mov dword ptr [0x8], ecx | rsp = 0x0, ecx = 0x1
[+] 14000100d | 8b442410 mov eax, dword ptr [0x10] | rsp = 0x0
[+] 140001011 | 8b4c2408 mov ecx, dword ptr [0x8] | rsp = 0x0
[+] 140001015 | 03c8 add ecx, eax | ecx = 0x1, eax = 0x2
[+] 140001017 | 8bc1 mov eax, ecx | ecx = 0x3
[+] 140001019 | 03442418 add eax, dword ptr [0x18] | eax = 0x3, rsp = 0x0
[+] 14000101d | c3 ret | rsp = 0x0
[+] 140001049 | 89442428 mov dword ptr [0x28], eax | rsp = 0x0, eax = 0x6
[+] 14000104d | 41b806000000 mov r8d, 0x6 |
[+] 140001053 | ba07000000 mov edx, 0x7 |
[+] 140001058 | b908000000 mov ecx, 0x8 |
[+] 14000105d | e89effffff call 0x140001000 | rsp = 0x0, rip = 0x0
snipoff
[+] 140004000 | 90 nop |
[=] Process returned from entrypoint (exit_trap)!
[+] Syscalls called:
[+] Registries accessed:
[+] Strings:
executing binary
=====================
F:\QILING\testqiling\printxcode.exe
=====================
[+] Profile: Default
[+] Map GDT at 0x30000 with GDT_LIMIT=4096
[+] Write to 0x30018 for new entry b'\x00\xf0\x00\x00\x00\xfeO\x00'
[+] Write to 0x30028 for new entry b'\x00\xf0\x00\x00\x00\x96O\x00'
[+] Write to 0x30070 for new entry b'\x00`\x00`\x00\xf6#\x00'
[+] Write to 0x30078 for new entry b'\x00\x00\x00\x00\x00\xf6#\x06'
[+] Windows Registry PATH: F:\QILING\examples\rootfs\x8664_windows\Windows\registry
[=] Initiate stack address at 0xfffdd000
[=] Loading F:\QILING\testqiling\printxcode.exe to 0x400000
[=] PE entry point at 0x402eda
[=] TEB addr is 0x6000
[=] PEB addr is 0x6044
[=] Loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll ...
[!] Warnings while loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll:
[!] - SizeOfHeaders is smaller than AddressOfEntryPoint: this file cannot run under Windows 8.
[!] - AddressOfEntryPoint lies outside the sections' boundaries. AddressOfEntryPoint: 0x0
[+] DLL preferred base address: 0x180000000
[+] DLL preferred base address exceeds memory upper bound, loading to: 0x10000000
[=] Done with loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\ntdll.dll
[=] Loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\kernel32.dll ...
[+] DLL preferred base address: 0x180000000
[+] DLL preferred base address exceeds memory upper bound, loading to: 0x101f0000
[=] Done with loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\kernel32.dll
[=] Loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\mscoree.dll ...
[+] DLL preferred base address: 0x10000000
[+] DLL preferred base address is taken, loading to: 0x102b0000
[=] Done with loading F:\QILING\examples\rootfs\x8664_windows\Windows\System32\mscoree.dll
[+] Done with loading F:\QILING\testqiling\printxcode.exe
[+] Setting up exit trap at 0x0xc000000
[+] 00402eda | ff2500204000 jmp dword ptr [0x402000] |
[!] api _CorExeMain is not implemented
[+] 102c4330 | 8bff mov edi, edi | edi = 0x0
[+] 102c4332 | 56 push esi | esp = 0x0, esi = 0xffffd000
snipoff
[+] 0c000000 | 90 nop |
[=] Process returned from entrypoint (exit_trap)!
[+] Syscalls called:
[+] Registries accessed:
[+] Strings:
Recently I have been trying to learn assembly x86 using NASM on a Windows platform, I am trying to make a function that reads a character from stdin ignoring any line feeds and carriage returns, but the problem is that when the function reaches the ret operation the program crashes, strangely when i run the function without the call to ReadConsoleA
the program finishes correctly.
Code:
section .bss
temp_char resb 1
bytes_written_holder resq 1
section .data
global _start
extern GetStdHandle, WriteConsoleA, ReadConsoleA, ExitProcess
section .text
getinput:
mov rcx, -10
call GetStdHandle
mov rcx, rax
mov rdx, temp_char
mov r8, 1
mov r9, bytes_written_holder
push 0
call ReadConsoleA
mov al, [temp_char]
cmp al, 0xa
je getinput
cmp al, 0xd
je getinput
ret
_start:
call getinput
mov rcx, -11
call GetStdHandle
mov rcx, rax
mov rdx, temp_char
mov r8, 1
mov r9, bytes_written_holder
push 0
call WriteConsoleA
mov rcx, 0
call ExitProcess
I am using NASM to assemble and GoLink to link:
nasm -f win64 printtest.s -o printtest.obj
GoLink.exe /console /entry _start printtest.obj kernel32.dll
I just encountered a weird issue with gdb, though I'm not sure, if I'm missing something.
Let's suppose I have these two files:
somefile.asm:
01 section .text
02
03 funca:
04 mov eax, 5
05 mov ebx, 5
06 cmp eax, ebx
07 je aisequal
08 mov ecx, 13
09 mov edx, 19
10 ret
11
12 aisequal:
13 mov ecx, 17
14 mov edx, 21
15 ret
and
somefile_test.asm:
01 %include "somefile.asm"
02
03 section .text
04 global _start
05
06 _start:
07 xor eax, eax
08 xor ebx, ebx
09 xor ecx, ecx
10 xor edx, edx
11 call funca
12
13 mov eax, 1
14 mov ebx, 0
15 int 0x80
I compile and link it using
nasm -f elf -g -F dwarf somefile_test.asm
ld -m elf_i386 -o somefile_test.out somefile_test.o
And then debug my application using gdb:
gdb somefile_test.out
I now set a breakpoint in the imported file:
GNU gdb (GDB) 10.1
(gdb) b somefile.asm:5
Breakpoint 1 at 0x8049000: file somefile.asm, line 5.
(gdb) r
Starting program: /<bla>/somefile_test.out
Breakpoint , funca () at somefile.asm:5
5 mov ebx, 5
Now appearantly, the execution stopped at the correct position. The next line to be executed would be 5, which is mov ebx, 5.
However, the last line should've been mov eax, 5 which should have already been executed. It was not:
(gdb) i r eax
eax 0x0 0
It gets even weirder:
(gdb) si
6 cmp eax, ebx
(gdb) i r eax ebx
eax 0x5 5
ebx 0x0 0
Now, eax is set, but ebx is not (yet).
If I execute the next line, it is set:
(gdb) si
7 je aisequal
(gdb) i r eax ebx
eax 0x5 5
ebx 0x5 5
However, I'd expect the program to jump to line 12 (aisequal) now, but it doesn't:
(gdb) si
8 mov ecx, 13
On the next instruction, it suddenly goes to the right line:
(gdb) si
14 mov edx, 21
(gdb) i r eax ebx edx
eax 0x5 5
ebx 0x5 5
edx 0x0 0
And so on:
(gdb) si
15 ret
(gdb) i r eax ebx ecx edx
eax 0x5 5
ebx 0x5 5
ecx 0x11 17
edx 0x0 0
If I put all my code in a single file, everything works as expected:
01 section .text
02 global _start
03
04 _start:
05 xor eax, eax
06 xor ebx, ebx
07 xor ecx, ecx
08 xor edx, edx
09 call funca
10
11 mov eax, 1
12 mov ebx, 0
13 int 0x80
14
15 funca:
16 mov eax, 5
17 mov ebx, 5
18 cmp eax, ebx
19 je aisequal
20 mov ecx, 13
21 mov edx, 19
22 ret
23
24 aisequal:
25 mov ecx, 17
26 mov edx, 21
27 ret
GBU gdb (GDB) 10.1
(gdb) b 16
Breakpoint 1 at 0x8049019: file singlefile.asm, line 16.
(gdb) r
Starting program: /<bla>/singlefile.out
Breakpoint 1, funca () at singlefile.asm:16
16 mov eax, 5
(gdb) i r eax ebx ecx edx
eax 0x0 0
ebx 0x0 0
ecx 0x0 0
edx 0x0 0
(gdb) si
17 mov ebx, 5
(gdb) i r eax ebx ecx edx
eax 0x5 5
ebx 0x0 0
ecx 0x0 0
edx 0x0 0
(gdb) si
18 cmp eax, ebx
(gdb) si
19 je aisequal
(gdb) si
25 mov ecx, 17
(gdb) si
26 mov edx, 21
(gdb) i r eax ebx ecx edx
eax 0x5 5
ebx 0x5 5
ecx 0x11 17
edx 0x0 0
(gdb) si
aisequal () at singlefile.asm:27
27 ret
(gdb) i r eax ebx ecx edx
eax 0x5 5
ebx 0x5 5
ecx 0x11 17
edx 0x15 21
(gdb) si
_start () at singlefile.asm:11
11 mov eax, 1
Now I've only picked up gdb two days ago, so I'm not that familiar with it.
Can someone explain to me what's happening?
Is this a bug or am I missing something?
I am using
nasm 2.15.05-1
binutils 2.35.1-1
gdb 10.1-4
gcc 10.2.0-4
on Linux 5.9.14-arch1-1 #1 SMP PREEMPT Sat, 12 Dec 2020 14:37:12 +0000 x86_64 GNU/Linux
This looks like a bug in nasm. It didn't reproduce for me using nasm-2.14.
GDB will only display source info that the compiler/assembler tells it. If the assembler puts out incorrect info, then GDB will display that incorrect info and can't do anything about it.
To verify that the problem is in nasm, run objdump -dS somefile_test.o and compare the assembly and source listing. If they are also off by one, it's a bug in nasm.
Here is what I see:
somefile_test.o: file format elf32-i386
Disassembly of section .text:
00000000 <funca>:
section .text
funca:
mov eax, 5
0: b8 05 00 00 00 mov $0x5,%eax
mov ebx, 5
5: bb 05 00 00 00 mov $0x5,%ebx
cmp eax, ebx
a: 39 d8 cmp %ebx,%eax
je aisequal
c: 74 0b je 19 <aisequal>
Note how instructions and source perfectly line up.
Apparently, this is a regression in nasm.
Reported it to them.
I'm writing a simple assembly program on Darwin x86_64 (MacOS 10.14.6) that creates a file (test.txt) and writes "E" to it. However, for some reason, the "E" is not written to the file. What am I doing wrong?
Here's my program:
global start
section .text
start:
;Create the file
mov rax, 0x2000005
mov rdi, fname
mov rsi, 0x200
mov rdx, 0o644
syscall
;Write to file
mov rdi, rax ;As far as I know, this uses the fd returned by creating a file (previous syscall)
mov rsi, msg
mov rdx, 1
mov rax, 0x2000004
syscall
;Exit
mov rax, 0x2000001
mov rdi, 0
syscall
section .data
msg: db "E" ;Message
fname: db "test.txt" ;File name
I have also tried this:
global start
section .text
start:
mov rax, 0x2000005
mov rdi, fname
mov rsi, 0x200
mov rdx, 0o644
syscall
mov rdi, rax
mov rsi, msg
mov rdx, 2
mov rax, 0x2000004
syscall
mov rax, 0x2000001
mov rdi, 0
syscall
section .data
msg: db "E", -1
fname: db "test.txt", 0
Yet neither work.
I found the answer:
I found that opening the file with create mode and write mode works.
global start
section .text
start:
;Open file with create mode and write mode
mov rax, 0x2000005
mov rdi, fname
mov rsi, 0x201
mov rdx, 0o644
syscall
;Now write
mov rdi, rax
mov rsi, msg
mov rdx, 1
mov rax, 0x2000004
syscall
;Exit
mov rax, 0x2000001
mov rdi, 0
syscall
section .data
msg: db "E"
fname: db "test.txt"
Also, here is an array of flags for opening files:
O_ACCMODE: 0x3
O_APPEND: 0x8
O_ASYNC: 0x40
O_CLOEXEC: 0x1000000
O_CREAT: 0x200
O_DIRECTORY: 0x100000
O_DSYNC: 0x400000
O_EXCL: 0x800
O_EXLOCK: 0x20
O_NDELAY: 0x4
O_NOCTTY: 0x20000
O_NOFOLLOW: 0x100
O_NONBLOCK: 0x4
O_RDONLY: 0x0
O_RDWR: 0x2
O_SHLOCK: 0x10
O_SYNC: 0x80
O_TRUNC: 0x400
O_WRONLY: 0x1
To combine, use the | operator (in C) or or (in assembly).