Details on gdb memory access complaint - macos

I have an object file compiled using as (from assembler code).
If I link it using ld, when I try to stepi (or nexti) gdb complains about memory access at address 0x0. If I link it using gcc, all is fine.
I am guessing the problem is caused by ld, which produces fewer sections when compared to the linking result of gcc.
Is there a way to configure gdb to be more verbose so I can maybe figure out what's wrong with the executable?
(gdb) b main
Breakpoint 1 at 0x100000f8e
(gdb) r
Breakpoint 1, 0x0000000100000f8e in main ()
(gdb) x/10i $pc
0x100000f8e <main>: fbld 0x6c(%rip) # 0x100001000 <data1>
0x100000f94 <main+6>: fimul 0x7a(%rip) # 0x100001014 <data2>
0x100000f9a <main+12>: fbstp 0x60(%rip) # 0x100001000 <data1>
0x100000fa0 <main+18>: mov0x0 $0x2000001,%rax
0x100000fa7 <main+25>: mov $,%rdi
0x100000fae <main+32>: syscall
(gdb) si
Cannot access memory at address 0x0
0x0000000100000f94 in main ()
PS: The executable itself runs as expected in both versions.
Later edit: commands i've used to compile:
as -arch x86_64 src.s -o src.o
ld -e _main -arch x86_64 src.o -o src
gcc -o src src.o

gdb has a "show debug" command, giving various internal debug settings. E.g. "set debug target 1" will turn on tracing for gdb's interaction with the target process. You might want to experiment with every flag they have (there aren't that many).

GCC doesn't actually do the linking, it just calls ld on your behalf. The options it's providing must be different from the ones you are using.
Per this thread:
How to get GCC linker command?
You should be able to see the ld invocation's command line by running gcc -v.
That should tell you how to modify your ld command line so things work for you.

Related

Bypass ptrace anti-debugging trick

I'm having some trouble bypassing calls to ptrace when debugging a 32-bit Linux executable.
I have this binary: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.26, BuildID[sha1]=b1579d4c55e90110491da76331c9a158b77a5729, stripped
and i have been trying to debug it. So due to it is a stripped binary i located the entry point using gdb.
gef➤ info file
Entry point: 0x804849c
.
.
.
other stuff
Once I got to the entry point, I printed out the next instructions:
gef➤ x/15i 0x804849c
0x804849c: xor ebp,ebp
0x804849e: pop esi
0x804849f: mov ecx,esp
0x80484a1: and esp,0xfffffff0
0x80484a4: push eax
0x80484a5: push esp
0x80484a6: push edx
0x80484a7: push 0x8048580
0x80484ac: push 0x8048590
0x80484b1: push ecx
0x80484b2: push esi
0x80484b3: push 0x8048480
0x80484b8: call 0x8048350 <__libc_start_main#plt>
0x80484bd: hlt
0x80484be: nop
I know 0x8048480 is the address of the main function. Now i placed a breakpoint at main (0x8048480) and then ran the program but i can't step into the breakpoint and the program exit with code 01. Therefore i decided to run strace ./binary command and ptrace calls inhibit me from debugging any further:
ptrace(PTRACE_TRACEME) = -1 EPERM (Operation not permitted)
To bypass this, i tried to use the LD_PRELOAD environment variable.
Hence i created a simple .c file:
long ptrace(int request, int pid, void *addr, void *data) {
return 0;
}
And compiled it as a shared library with the following command:
gcc -fPIC -shared -m32 ptrace.c -o ptrace.so
Here the output of the command file ptrace.so
ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=a9de523da44299f76ad94373a07c9c5f6f3c76db, not stripped
Next I set the environment variable LD_PRELOAD in the shell using export LD_PRELOAD=./ptrace.so command first, and then within gdb set environment LD_PRELOAD=./ptrace.so
but this is the output:
ERROR: ld.so: object './ptrace.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
How can i bypass the ptrace call??
Thank you.
To bypass this, i tried to use the LD_PRELOAD environment variable.
If the application is employing anti-debugging tricks, it is exceedingly likely that it executes ptrace system call directly, rather than via libc wrapper. LD_PRELOAD will not work in that case.
This command:
gcc -shared ptrace.c -o ptrace.so
builds a 64-bit binary on a 64-bit system. You want:
gcc -fPIC -shared -m32 ptrace.c -o ptrace.so

GDB symbols work for "break" and "print", but "list" fails with "No debugging symbols found"

There are tons of questions and answers about GDB and the "No debugging symbols found" warning, but all of those assume that the debugging symbols are not part of the .elf file.
I'm dealing with the following:
I have a .elf file with debugging symbols. I can verify this by doing objdump, and seeing a disassembly with the subroutine labels being present.
When I load the .elf file, it loads file correctly.
When I then do list to list the C code, I get No symbol table is loaded. Use the "file" command.
However, I can still do things like break main or p/x global_cntr!
When I do file progmem.elf, there's no difference in behavior: I get (No debugging symbols found in progmem.elf), but breakpoints etc still work.
GCC and GDB are using the same version of the GCC toolchain
I tried using -gdwarf-3 instead of -ggdb. No difference.
I'm lost...
I'm using a RISC-V toolchain, if that matters.
Here's an excerpt of my Makefile:
TARGET = $(TOOLS_PREFIX)/riscv32-unknown-elf
AS = $(TARGET)-as
ASFLAGS = -march=$(MARCH) -mabi=ilp32
LD = $(TARGET)-gcc
LDFLAGS = -march=$(MARCH) -g -mabi=ilp32 -Wl,-Tsections.lds,-Map,progmem.map -ffreestanding -nostartfiles -Wl,--no-relax
CC = $(TARGET)-gcc
CFLAGS = -march=$(MARCH) -g -ggdb -mno-div -mabi=ilp32 -Wall -Wextra -pedantic -DCPU_FREQ=$(CPU_FREQ_MHZ)000000 $(CC_OPT)
...
progmem.elf: $(OBJ_FILES) top_defines.h sections.lds Makefile
$(LD) $(LDFLAGS) -o $# $(OBJ_FILES) -lm
And here's a log of my GDB session:
/opt/riscv32im/bin//riscv32-unknown-elf-gdb progmem.elf \
-ex "target remote localhost:3333"
...
Remote debugging using localhost:3333
0x0000002e in rdcycle64 ()
(gdb)
(gdb)
(gdb) monitor soft_reset_halt
requesting target halt and executing a soft reset
(gdb) file progmem.elf
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from progmem.elf...
(No debugging symbols found in progmem.elf)
(gdb) br main
Breakpoint 1 at 0x5d6
(gdb) load
Loading section .memory, size 0x5790 lma 0x0
Start address 0x0, load size 22416
Transfer rate: 23 KB/sec, 11208 bytes/write.
(gdb) c
Continuing.
Program stopped.
0x000005d6 in main ()
(gdb) p/x global_cntr
$1 = 0x0
(gdb) l
No symbol table is loaded. Use the "file" command.
(gdb)
I have a .elf file with debugging symbols. I can verify this by doing objdump, and seeing a disassembly with the subroutine labels being present.
Debugging symbols are not the same as symbols. For disassembly, you only need the latter. For source listing you need the former.
I can still do things like break main or p/x global_cntr!
These also require only the symbol table.
You can confirm that you don't have debug symbols using objdump -g progmem.elf or readelf -wi progmem.elf.
Your command lines look like debug symbols should be included, but there is no telling what you do with .debug_* sections in your sections.lds linker script. Probably you discard them, which would explain why they aren't there.
Update:
Do you by any chance has an example sections.lds file that has them included?
ld --verbose should print the default linker script. Here is one example.
My original linker script was the following:
SECTIONS {
.memory : {
. = 0x00000;
start*(.text);
*(.text);
*(*);
end = .;
}
}
I suspect that my issue was caused by the catchall *(*); which moved all sections into the .text section.
I replaced it with the following script:
MEMORY
{
ram (ax) : ORIGIN = 0x00000000, LENGTH = 16K
}
SECTIONS {
}
After this, .debug_* symbols are included.
This script should be refined with more precise placement of various sections, but it's good enough to unblock me.

are there debugging options for ld

I have written an assembly program that, for testing purposes, just exits. The code is as follows:
section .text
_global start
_start:
mov eax, 1
mov ebx, 0
int 0x80
The program is obviously in 32-bit; however, I am using 1 64-bit processor and operating system, so I compiled it (using nasm) and linked it as follows:
nasm -f elf exit.asm
ld -m elf_i386 -s -o exit exit.o
debugging the program with gdb, I can't list the code since there are no debugging symbols.
(gdb) list
No symbol table is loaded. Use the "file" command.
In using gcc, you can use the options -ggdb to load the symbols while compiling a c file. but since I don't how to use gcc to compile 32-bit assembly for 64-bit machines (I have searched this but can't find a solution,) I am forced to use ld. can I load the debugging symbols using ld? sorry for the long question and the excess information. Thanks in advance.
Debugging information is generated by nasm when you pass -g. Additionally, you also need to specify what type of debugging information you want (typically dwarf), which is done with the -F switch. So to assemble your file, write
nasm -f elf -F dwarf -g file.asm
then link without -s to preserve the symbol table and debugging information:
ld -m elf_i386 -o file file.o
The -s switch tells ld to "strip" the debugging info. Lose that!

ld MinGW link to standard C library

I have a problem with following code.
extern printf
global _main
main:
push msg
call printf
ret
msg db "Hello world",0
I assemble this with NASM using nasm -fwin32 test.asm Then i link it using ld test.obj.
And it tells me "test.obj:test.asm:(text+0x6): undefined reference to 'printf'"
How to link my file to standard C libraries? I have ld from latest MinGW.
To assemble code :
nasm -fwin32 test.asm
Microsoft will prefix functions using the cdecl calling convention with a underscore.
To be match to the C calling convention printf should be _printf.
The same applies for _main instead of main.
And link with:
ld test.obj -lmsvcrt -entry=_main -subsystem=console -o test.exe
Here -entry command line option is used to invoking ld to specify the entry point for program .
Then use -l options to pass msvcrt library to the ld linker, otherwise you will get an error message, (undefined reference to `printf') which means that the linker did not found the symbol printf in the specified object file produced by NASM.
Here is completed source:
global _main
extern _printf
section .text
_main:
push msg
call _printf
add esp, 4 ;adjust the stack
ret
msg db "Hello world",0
I can see several issues with your code. First, you've got an underscore on global _main but not on main:. These should match. You can either use underscores throughout, or - what I would do - not at all... and for Windows, assemble as nasm -f win32 --prefix _ test.asm. This would make it "portable" in that, for Linux, it would assemble, without the --prefix _ without the underscores. Linux doesn't use underscores on global or extern symbols. If, by some chance, you were using OpenWatcom C, you could use --postfix _. Yeah, OpenWatcom uses trailing underscores. Yeah, I know they told us C was standardized. but once you get under the hood, this isn't really true.
The other big issue is that after calling _printf, you need to add esp, 4 (or pop a dummy register) to "clean up the stack". If you're using Windows APIs, they use the STDCALL calling convention in which "callee cleans up", so you don't want to do this. Mixing C calls (CDECL calling convention) and Windows APIs might get confusing, but should work.
I think Carl has the right idea with using gcc to link it. There's nothing to "compile", but gcc knows the proper command line to ld. gcc -o test.exe test.obj will probably be enough (maybe add -m32 if the latest MinGW expects to be doing 64-bit code). This will link in some "startup code" which calls _main. This will increase the size of your executable slightly, and you "might" be able to get along without it, but it's easier to just do it.
In Linux, we can use ld directly (the command line is horrid), but ld is looking for _start, not main, as the entrypoint. We can tell ld -e main, but this entrypoint is not called(!) and there's no possible way to ret from it! The situation is probably different in Windows. You would need - as a bare minimum - -lc to tell ld that we want those C libraries. Easiest to "let gcc do it" - it won't touch your .asm code (but does link in that "startup code"). Happy Hello World! :)
Use a compiler front-end to link:
cc test.obj
If you really want to use ld directly (and you shouldn't), use the -v flag to cc to figure out what complete command line you need. For example, on my machine, it's:
ld -demangle -dynamic -arch x86_64 -macosx_version_min 10.8.0 \
-o a.out test.obj -lSystem \
/usr/bin/../lib/clang/4.2/lib/darwin/libclang_rt.osx.a
If I use GCC instead of Clang, it's even crazier:
ld -dynamic -arch x86_64 -macosx_version_min 10.8.4 -weak_reference_mismatches \
non-weak -o a.out -lcrt1.10.6.o \
-L/usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/x86_64 \
-L/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1/x86_64 \
-L/usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1 \
-L/usr/llvm-gcc-4.2/bin/../lib/gcc \
-L/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1 \
-L/usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/../../.. \
-L/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1/../../.. \
test.obj -lgcc -lSystem

Can't link assembly file in Mac OS X using ld

I'm trying to run a basic assembly file using 64 Bit Mac OS X Lion, using nasm and ld which are installed by default with Xcode.
I've written an assembly file, which prints a character, and I got it to build using nasm.
nasm -f elf -o program.o main.asm
However, when I go to link it with ld, it fails with quite a few errors/warnings:
ld -o program program.o
ld: warning: -arch not specified
ld: warning: -macosx_version_min not specificed, assuming 10.7
ld: warning: ignoring file program.o, file was built for unsupported file format which is not the architecture being linked (x86_64)
ld: warning: symbol dyld_stub_binder not found, normally in libSystem.dylib
ld: entry point (start) undefined. Usually in crt1.o for inferred architecture x86_64
So, I tried to rectify a few of these issues, and got nowhere.
Here's one of things I've tried:
ld -arch i386 -e _start -o program program.o
Which I thought would work, but I was wrong.
How do you make the object file a compatible architecture that nasm and ld will agree with?
Also, how would you define the entry point in the program (right now I'm using global _start in .section text, which is above _start, which doesn't seem to do much good.)
I'm a bit confused as to how you would successfully link an object file to a binary file using ld, and I think I'm just missing some code (or argument to nasm or ld) that will make them agree.
Any help appreciated.
You need to use global start and start:, no underscore. Also, you should not be using elf as the arch. Here is a bash script I use to assemble my x86-64 NASM programs on Mac OS X:
#!/bin/bash
if [[ -n "$1" && -f "$1" ]]; then
filename="$1"
base="${filename%%.*}"
ext="${filename##*.}"
nasm -f macho64 -Ox "$filename" \
&& ld -macosx_version_min 10.7 "${base}.o" -o "$base"
fi
If you have a file called foo.s, this script will first run
nasm -f macho64 -Ox foo.s
Which will create foo.o. The -Ox flag makes NASM do some extra optimization with jumps (i.e. making them short, near or far) so that you don't have to do it yourself. I'm using x86-64, so my code is 64-bit, but it looks like you're trying to assemble 32-bit. In that case, you would use -f macho32. See nasm -hf for a list of valid output formats.
Now, the object file will be linked:
ld -macosx_version_min 10.7 foo.o -o foo
I've set the -macosx_version_min option to quiet NASM down and prevent a warning. You don't have to set it to Lion (10.7). This will create an executable called foo. With any luck, typing ./foo and hitting return should run your program.
In regard to the ld: warning: symbol dyld_stub_binder not found, normally in libSystem.dylib warning, I get that every time too and I'm not sure why, but everything seems fine when I run the executable.
OK, looking at your samples I assume you either used a generic nasm or linux assembly tutorial.
The first thing you need to take care of is the binary format created by nasm.
Your post states:
ld: warning: ignoring file program.o, file was built for unsupported file format which is not the architecture being linked (x86_64)
Thats the result of the '-f elf' parameter which tells nasm you want a 32bit ELF object (which would be the case for e.g. linux). But since you're on OSX what you want is a Mach-O object.
Try the following:
nasm -f macho64 -o program.o main.asm
gcc -o program program.o
Or if you wan't to create a 32bit binary:
nasm -f macho32 -o program.o main.asm
gcc -m32 -o program program.o
Regarding the _start symbol - if you wan't to create a simple program that will be able
to use the provided libc system functions then you shouldn't use _start at al.
It's the default entry point ld will look for and normaly it's provided in your libc / libsystem.
I suggest you try to replace the _start in your code by something like '_main'
and link it like the example above states.
A generic libc-based assembly template for nasm could look like this:
;---------------------------------------------------
.section text
;---------------------------------------------------
use32 ; use64 if you create 64bit code
global _main ; export the symbol so ld can find it
_main:
push ebp
mov ebp, esp ; create a basic stack frame
[your code here]
pop ebp ; restore original stack
mov eax, 0 ; store the return code for main in eax
ret ; exit the program
In addition to this I should mention that any call's you do on OSX need to use an aligned stack frame or your code will just crash.
There are some good tutorials on that out there too - try searching for OSX assembly guide.
It's probably easier just to let gcc do the heavy lifting for you, rather than trying to drive ld directly, e.g.
$ gcc -m32 program.o -o program
The mac gcc compiler won't link elf objects. You need a cross compiler...
http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux
Then you can proceed with something similar to this...
/usr/local/gcc-4.8.1-for-linux32/bin/i586-pc-linux-ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o

Resources