How to print disassembly registers in the Xcode console - objective-c

I'm looking at some disassembly code and see something like 0x01c8f09b <+0015> mov 0x8(%edx),%edi and I am wondering what the value of %edx or %edi is.
Is there a way to print the value of %edx or other assembly variables? Is there a way to print the value at the memory address that %edx points at (I'm assuming edx is a register containing a pointer to ... something here).
For example, you can print an objet by typing po in the console, so is there a command or syntax for printing registers/variables in the assembly?
Background:
I'm getting EXC_BAD_ACCESS on this line and I would like to debug what is going on. I'm aware this error is related to memory management and I'm looking at figuring out where I may be missing/too-many retain/release/autorelease calls.
Additional Info:
This is on IOS, and my application is running in the iPhone simulator.

You can print a register (e.g, eax) using:
print $eax
Or for short:
p $eax
To print it as hexadecimal:
p/x $eax
To display the value pointed to by a register:
x $eax
Check the gdb help for more details:
help print
help x

Depends up which Xcode compiler/debugger you are using. For gcc/gdb it's
info registers
but for clang/lldb it's
register read

(gdb) info reg
eax 0xe 14
ecx 0x2844e0 2639072
edx 0x285360 2642784
ebx 0x283ff4 2637812
esp 0xbffff350 0xbffff350
ebp 0xbffff368 0xbffff368
esi 0x0 0
edi 0x0 0
eip 0x80483f9 0x80483f9 <main+21>
eflags 0x246 [ PF ZF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
From Debugging with gdb:
You can refer to machine register contents, in expressions, as variables with names
starting with `$'. The names of registers are different for each machine; use info
registers to see the names used on your machine.
info registers
Print the names and values of all registers except floating-point
registers (in the selected stack frame).
info all-registers
Print the names and values of all registers, including floating-point
registers.
info registers regname ...
Print the relativized value of each specified register regname.
regname may be any register name valid on the machine you are using,
with or without the initial `$'.

If you are using LLDB instead of GDB you can use register read

Those are not variables, but registers.
In GDB, you can see the values of standard registers by using the following command:
info registers
Note that a register contains integer values (32bits in your case, as the register name is prefixed by e). What it represent is not known. It can be a pointer, an integer, mostly anything.
If po crashes when you try to print a register's value as a pointer, it's likely that the value is not a pointer (or an invalid one).

Related

Valgrind reports "invalid write" at "X bytes below stack pointer"

I'm running some code under Valgrind, compiled with gcc 7.5 targeting an aarch64 (ARM 64 bits) architecture, with optimizations enabled.
I get the following error:
==3580== Invalid write of size 8
==3580== at 0x38865C: ??? (in ...)
==3580== Address 0x1ffeffdb70 is on thread 1's stack
==3580== 16 bytes below stack pointer
This is the assembly dump in the vicinity of the offending code:
388640: a9bd7bfd stp x29, x30, [sp, #-48]!
388644: f9000bfc str x28, [sp, #16]
388648: a9024ff4 stp x20, x19, [sp, #32]
38864c: 910003fd mov x29, sp
388650: d1400bff sub sp, sp, #0x2, lsl #12
388654: 90fff3f4 adrp x20, 204000 <_IO_stdin_used-0x4f0>
388658: 3dc2a280 ldr q0, [x20, #2688]
38865c: 3c9f0fe0 str q0, [sp, #-16]!
I'm trying to ascertain whether this is a possible bug in my code (note that I've thoroughly reviewed my code and I'm fairly confident it's correct), or whether Valgrind will blindly report any writes below the stack pointer as an error.
Assuming the latter, it looks like a Valgrind bug since the offending instruction at 0x38865c uses the pre-decrement addressing mode, so it's not actually writing below the stack pointer.
Furthermore, at address 0x388640 a similar access (and again with pre-decrement addressing mode) is performed, yet this isn't reported by Valgrind; the main difference being the use of an x register at address 0x388640 versus a q register at address 38865c.
I'd also like to draw attention to the large stack pointer subtraction at 0x388650, which may or may not have anything to do with the issue (note this subtraction makes sense, given that the offending C code declares a large array on the stack).
So, will anyone help me make sense of this, and whether I should worry about my code?
The code looks fine, and the write is certainly not below the stack pointer. The message seems to be a valgrind bug, possibly #432552, which is marked as fixed. OP confirms that the message is not produced after upgrading valgrind to 3.17.0.
code declares a large array on the stack
should [I] worry about my code?
I think it depends upon your desire for your code to be more portable.
Take this bit of code that I believe represents at least one important thing you mentioned in your post:
#include <stdio.h>
#include <stdlib.h>
long long foo (long long sz, long long v) {
long long arr[sz]; // allocating a variable on the stack
arr[sz-1] = v;
return arr[sz-1];
}
int main (int argc, char *argv[]) {
long long n = atoll(argv[1]);
long long v = foo(n, n);
printf("v = %lld\n", v);
}
$ uname -mprsv
Darwin 20.5.0 Darwin Kernel Version 20.5.0: Sat May 8 05:10:33 PDT 2021; root:xnu-7195.121.3~9/RELEASE_X86_64 x86_64 i386
$ gcc test.c
$ a.out 1047934
v = 1047934
$ a.out 1047935
Segmentation fault: 11
$ uname -snrvmp
Linux localhost.localdomain 3.19.8-100.fc20.x86_64 #1 SMP Tue May 12 17:08:50 UTC 2015 x86_64 x86_64
$ gcc test.c
$ ./a.out 2147483647
v = 2147483647
$ ./a.out 2147483648
v = 2147483648
There are at least some minor portability concerns with this code. The amount of allocatable stack memory for these two environments differs significantly. And that's only for two platforms. Haven't tried it on my Windows 10 vm but I don't think I need to because I got bit by this one a long time ago.
Beyond OP issue that was due to a Valgrind bug, the title of this question is bound to attract more people (like me) who are getting "invalid write at X bytes below stack pointer" as a legitimate error.
My piece of advice: check that the address you're writing to is not a local variable of another function (not present in the call stack)!
I stumbled upon this issue while attempting to write into the address returned by yyget_lloc(yyscanner) while outside of function yyparse (the former returns the address of a local variable in the latter).

gdb crash when using breakpoints

In every program I try to debug, I am getting the same result, every time I use breakpoints and try to run any program gdb crash. I tried the same thing on different programs and it keeps acting like this.
I will show the result on this simple:
int main(int argc,char* argv[]){
for(int i = 0;i < 200; i++){
printf("%d\n",i);
}
}
gcc main.c -m32 -std=c99 -o test
GNU gdb (Debian 8.3-1) 8.3
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
(No debugging symbols found in test)
(gdb) disas main
Dump of assembler code for function main:
0x00001199 <+0>: lea 0x4(%esp),%ecx
0x0000119d <+4>: and $0xfffffff0,%esp
0x000011a0 <+7>: pushl -0x4(%ecx)
0x000011a3 <+10>: push %ebp
0x000011a4 <+11>: mov %esp,%ebp
0x000011a6 <+13>: push %ebx
0x000011a7 <+14>: push %ecx
0x000011a8 <+15>: sub $0x10,%esp
0x000011ab <+18>: call 0x10a0 <__x86.get_pc_thunk.bx>
0x000011b0 <+23>: add $0x2e50,%ebx
0x000011b6 <+29>: movl $0x0,-0xc(%ebp)
0x000011bd <+36>: jmp 0x11d8 <main+63>
0x000011bf <+38>: sub $0x8,%esp
0x000011c2 <+41>: pushl -0xc(%ebp)
0x000011c5 <+44>: lea -0x1ff8(%ebx),%eax
0x000011cb <+50>: push %eax
0x000011cc <+51>: call 0x1030 <printf#plt>
0x000011d1 <+56>: add $0x10,%esp
0x000011d4 <+59>: addl $0x1,-0xc(%ebp)
0x000011d8 <+63>: cmpl $0xc7,-0xc(%ebp)
0x000011df <+70>: jle 0x11bf <main+38>
0x000011e1 <+72>: mov $0x0,%eax
0x000011e6 <+77>: lea -0x8(%ebp),%esp
0x000011e9 <+80>: pop %ecx
0x000011ea <+81>: pop %ebx
0x000011eb <+82>: pop %ebp
0x000011ec <+83>: lea -0x4(%ecx),%esp
0x000011ef <+86>: ret
End of assembler dump.
(gdb) break *0x000011ef
Breakpoint 1 at 0x11ef
(gdb) run
Starting program: /root/test
[1]+ Stopped gdb test
I tried to do the same thing in another linux machine, and it works fine. So what could be the problem?
Update: I found a temp solution for the breakpoints issue (so gdb do not crash), You use the command (start) at the beginning and everything will work fine :
GNU gdb (Debian 8.3-1) 8.3
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
(No debugging symbols found in test)
(gdb) start
Temporary breakpoint 1 at 0x11a8
Starting program: /root/test
Temporary breakpoint 1, 0x565561a8 in main ()
(gdb) enable
(gdb) disas main
Dump of assembler code for function main:
0x56556199 <+0>: lea 0x4(%esp),%ecx
0x5655619d <+4>: and $0xfffffff0,%esp
0x565561a0 <+7>: pushl -0x4(%ecx)
0x565561a3 <+10>: push %ebp
0x565561a4 <+11>: mov %esp,%ebp
0x565561a6 <+13>: push %ebx
0x565561a7 <+14>: push %ecx
=> 0x565561a8 <+15>: sub $0x10,%esp
0x565561ab <+18>: call 0x565560a0 <__x86.get_pc_thunk.bx>
0x565561b0 <+23>: add $0x2e50,%ebx
0x565561b6 <+29>: movl $0x0,-0xc(%ebp)
0x565561bd <+36>: jmp 0x565561d8 <main+63>
0x565561bf <+38>: sub $0x8,%esp
0x565561c2 <+41>: pushl -0xc(%ebp)
0x565561c5 <+44>: lea -0x1ff8(%ebx),%eax
0x565561cb <+50>: push %eax
0x565561cc <+51>: call 0x56556030 <printf#plt>
0x565561d1 <+56>: add $0x10,%esp
0x565561d4 <+59>: addl $0x1,-0xc(%ebp)
0x565561d8 <+63>: cmpl $0xc7,-0xc(%ebp)
0x565561df <+70>: jle 0x565561bf <main+38>
0x565561e1 <+72>: mov $0x0,%eax
0x565561e6 <+77>: lea -0x8(%ebp),%esp
0x565561e9 <+80>: pop %ecx
0x565561ea <+81>: pop %ebx
0x565561eb <+82>: pop %ebp
0x565561ec <+83>: lea -0x4(%ecx),%esp
0x565561ef <+86>: ret
End of assembler dump.
(gdb) break *0x565561df
Breakpoint 2 at 0x565561df
(gdb) info break
Num Type Disp Enb Address What
2 breakpoint keep y 0x565561df <main+70>
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/test
Breakpoint 2, 0x565561df in main ()
(gdb) step
Single stepping until exit from function main,
which has no line number information.
0
Breakpoint 2, 0x565561df in main ()
(gdb)
Single stepping until exit from function main,
which has no line number information.
1
Breakpoint 2, 0x565561df in main ()
(gdb)
Single stepping until exit from function main,
which has no line number information.
2
Breakpoint 2, 0x565561df in main ()
(gdb)
Single stepping until exit from function main,
which has no line number information.
3
Breakpoint 2, 0x565561df in main ()
(gdb)
Single stepping until exit from function main,
which has no line number information.
4
Breakpoint 2, 0x565561df in main ()
Unfortunately, This is a temp solution just so you can deal with breakpoints, and it have nothing to do with the crashing problem.
You are most likely trying to set a breakpoint at an invalid address with this command break *0x000011ef. The 0x11ef is the offset of that instruction within the section within the ELF, but the program is going to be relocated when it is loaded / started.
You should instead try start, then disas main, and then place your breakpoint.
GDB stopping like this is a bug which occurs when GDB throws an error while trying to place a breakpoint, it was fixed in upstream GDB with this patch:
https://sourceware.org/ml/gdb-patches/2019-05/msg00361.html
Once you see GDB stopped like this:
[1]+ Stopped gdb soQuestionProgram
you should be dropped back to a shell. Just resume GDB with the fg command and continue your debug session. Once GDB 8.4 is out this bug will be fixed.
it keeps acting like this
First: GDB did not crash. It merely got stopped (by your shell). You can get it back with the shell fg command.
Second: this has nothing to do with GDB, and something to do with your terminal configuration. Using reset may cure this problem.

Showing high and low PC of every program functions using DWARF library

I am trying to make this code work : https://github.com/eliben/code-for-blog/blob/master/2011/dwarf_get_func_addr.c
It is extracted from a tutorial made by Eli Bendersky on http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information
Unfortunately, low pc and high pc return always the same address for almost every function:
DW_TAG_subprogram: 'aFunctionName'
low pc : 0x00000001
high pc : 0x7f3a00000001
Whereas if objdump --dwarf=decodedline ./lulesh_normal >> dump_dwarf.txt
gives me :
File name Line number Starting address
lulesh.cc 1297 0x402e00
lulesh.cc 1297 0x402e11
lulesh.cc 1299 0x402ee4
lulesh.cc 1300 0x402ef0
lulesh.cc 1301 0x402ef6
lulesh.cc 1299 0x402f00
[...]
So it manages to link line and address but not to find the real address of the functions.
Any idea why ?
Thank you for your help,
The code in dwarf_get_func_addr.c has at least one bug: it assumes that every function has DW_AT_low_pc and DW_AT_high_pc attributes, and will print uninitialized values if that is not the case.
You should initialize lowpc = highpc = -1; on line 42, so as not to print unintialized values.
Other than that, it's impossible to help you without access to your lulesh_normal binary.
You should do readelf -wi lulesh_normal, and then step through list_func_in_die in a debugger, and compare what the program is reading there with the output from readelf -- they should match one to one. If they don't, your version of libdwarf is possibly buggy.

Statically Defined IDT

This question already has answers here:
Solution needed for building a static IDT and GDT at assemble/compile/link time
(1 answer)
How to do computations with addresses at compile/linking time?
(2 answers)
Closed 5 days ago.
I'm working on a project that has tight boot time requirements. The targeted architecture is an IA-32 based processor running in 32 bit protected mode. One of the areas identified that can be improved is that the current system dynamically initializes the processor's IDT (interrupt descriptor table). Since we don't have any plug-and-play devices and the system is relatively static, I want to be able to use a statically built IDT.
However, this proving to be troublesome for the IA-32 arch since the 8 byte interrupt gate descriptors splits the ISR address. The low 16 bits of the ISR appear in the first 2 bytes of the descriptor, some other bits fill in the next 4 bytes, and then finally the last 16 bits of the ISR appear in the last 2 bytes.
I wanted to use a const array to define the IDT and then simply point the IDT register at it like so:
typedef struct s_myIdt {
unsigned short isrLobits;
unsigned short segSelector;
unsigned short otherBits;
unsigned short isrHibits;
} myIdtStruct;
myIdtStruct myIdt[256] = {
{ (unsigned short)myIsr0, 1, 2, (unsigned short)(myIsr0 >> 16)},
{ (unsigned short)myIsr1, 1, 2, (unsigned short)(myIsr1 >> 16)},
etc.
Obviously this won't work as it is illegal to do this in C because myIsr is not constant. Its value is resolved by the linker (which can do only a limited amount of math) and not by the compiler.
Any recommendations or other ideas on how to do this?
You ran into a well known x86 wart. I don't believe the linker can stuff the address of your isr routines in the swizzled form expected by the IDT entry.
If you are feeling ambitious, you could create an IDT builder script that does something like this (Linux based) approach. I haven't tested this scheme and it probably qualifies as a nasty hack anyway, so tread carefully.
Step 1: Write a script to run 'nm' and capture the stdout.
Step 2: In your script, parse the nm output to get the memory address of all your interrupt service routines.
Step 3: Output a binary file, 'idt.bin' that has the IDT bytes all setup and ready for the LIDT instruction. Your script obviously outputs the isr addresses in the correct swizzled form.
Step 4: Convert his raw binary into an elf section with objcopy:
objcopy -I binary -O elf32-i386 idt.bin idt.elf
Step 5: Now idt.elf file has your IDT binary with the symbol something like this:
> nm idt.elf
000000000000000a D _binary_idt_bin_end
000000000000000a A _binary_idt_bin_size
0000000000000000 D _binary_idt_bin_start
Step 6: relink your binary including idt.elf. In your assembly stubs and linker scripts, you can refer to symbol _binary_idt_bin_start as the base of the IDT. For example, your linker script can place the symbol _binary_idt_bin_start at any address you like.
Be careful that relinking with the IDT section doesn't move anyting else in your binary, e.g. your isr routines. Manage this in your linker script (.ld file) by puting the IDT into it's own dedicated section.
---EDIT---
From comments, there seems to be confusion about the problem. The 32-bit x86 IDT expects the address of the interrupt service routine to be split into two different 16-bit words, like so:
31 16 15 0
+---------------+---------------+
| Address 31-16 | |
+---------------+---------------+
| | Address 15-0 |
+---------------+---------------+
A linker is thus unable to plug-in the ISR address as a normal relocation. So, at boot time, software must construct this split format, which slows boot time.

How to jump into bootloader in Ada?

I am writing embedded code in Ada. I want to jump into bootloader code which is located at address 0x0E00. I am trying to use following code:
with Interfaces; use Interfaces;
with System;
package AVR.bootloader is
procedure Call;
pragma No_Return(Call);
pragma Import (Assembler,Call);
for Call'Address use System'To_Address (16#0E00#);
end AVR.bootloader;
The problem is this does not work.
Edit: I want to do a following C equivalent:
void (*boot)(void)=0x0E00;
I did a small experiment on this Macbook Pro, and your code seems to do what you meant it to; I modified the code to read
with System;
procedure Bootloader is
procedure Call;
pragma No_Return (Call);
pragma Import (Assembler, Call);
for Call'Address use System'To_Address (16#0E00#);
begin
Call;
end Bootloader;
and when I compile with gnatmake -c -u -f -S bootloader.adb the saved assembler is
.text
.globl __ada_bootloader
__ada_bootloader:
LFB1:
pushq %rbp
LCFI0:
movq %rsp, %rbp
LCFI1:
subq $16, %rsp
LCFI2:
movq $3584, -8(%rbp)
movq -8(%rbp), %rax
call *%rax
leave
LCFI3:
ret
[...]
which looks hopeful, though I’m not familiar enough with asm to know.
Running it under gdb I get (after a lot of chatter)
(gdb) run
Starting program: /Users/simon/tmp/bootloader
Reading symbols for shared libraries ++........................ done
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000e00
0x0000000000000e00 in ?? ()
(gdb) bt
#0 0x0000000000000e00 in ?? ()
Cannot access memory at address 0xe00
#1 0x0000000100000d93 in main (argc=1, argv=140734799805048, envp=140734799805064) at /Users/simon/tmp/b~bootloader.adb:121
#2 0x0000000100000bf4 in start ()
which looks even more hopeful.
Perhaps your AVR compiler isn’t code-generating properly?
Since normally a boot-loader runs on reset, the simplest method is to force a processor reset. A boot-loader may reasonably assume that it is running on an uninitialised system in reset state and may perform initialisation that is not valid on an already initialised system, so forcing a reset is the safest method.
Your processor may have a reset instruction or a reset controller that can perform this directly. Failing that it may have a watchdog timer that can generate a reset. Start the watchdog timer with a suitably short time-out and let it run without servicing it.