How to jump into bootloader in Ada? - embedded

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.

Related

DLL silently ignored even though the library links

I'm using a third part DLL that I've used successfully for ages. Now the linker links the dll lib without complaint but the exe doesn't load the dll.
I recently upgraded from the 32 bit to 64 bit cygwin.
I'm doing a mingw cross compile to 32 bits.
I'm trying to use the FTDI USB interface FTD2XX dll.
I have the version 2.04.06 FTD2XX lib, .h, and dll.
I had been using that dll successfully for ages but with older versions of cygwin and mingw.
Recently upgraded to cygwin64.
The app appears to link with the FTD2XX.lib without complaint.
But when I run the app it doesn't seem to look for or load the FTD2XX.dll.
The app runs but crashes as soon as it tries to call something in FTD2XX dll.
I created a simple hello_dll.dll for side by side test. That works.
The app.c does calls on both hello_dll.dll and ftd2xx.dll.
Is starts without complain, successfully calls function in hello_dll, and then it crashes on a call to ft2xx.dll.
(I renamed the lib to ftd2xx_2.04.06 to distinguish them from other versions I have. Newer versions don't work any better.)
Link with -verbose gives:
i686-w64-mingw32-gcc -Wall -m32 -g -O2 -c -I . -o app.o app.c
i686-w64-mingw32-gcc -Wall -m32 -o app.exe app.o -Wl,-verbose -L. -lhello_dll -lftd2xx_2.04.06
GNU ld (GNU Binutils) 2.34.50.20200227
Supported emulations:
i386pe
using internal linker script:
<snip>
/usr/lib/gcc/i686-w64-mingw32/9.2.0/../../../../i686-w64-mingw32/bin/ld: mode i386pe
attempt to open /usr/i686-w64-mingw32/sys-root/mingw/lib/../lib/crt2.o succeeded
/usr/i686-w64-mingw32/sys-root/mingw/lib/../lib/crt2.o
attempt to open /usr/lib/gcc/i686-w64-mingw32/9.2.0/crtbegin.o succeeded
/usr/lib/gcc/i686-w64-mingw32/9.2.0/crtbegin.o
attempt to open app.o succeeded
app.o
<snip>
attempt to open ./hello_dll.lib succeeded
./hello_dll.lib
(./hello_dll.lib)d000001.o
(./hello_dll.lib)d000000.o
(./hello_dll.lib)d000002.o
<snip>
attempt to open ./ftd2xx_2.04.06.lib succeeded
./ftd2xx_2.04.06.lib
(./ftd2xx_2.04.06.lib)FTD2XX.dll
(./ftd2xx_2.04.06.lib)FTD2XX.dll
(./ftd2xx_2.04.06.lib)FTD2XX.dll
(./ftd2xx_2.04.06.lib)FTD2XX.dll
::::::::::::::::::::::::::::
I obtained a 32 bit compatible version of gdb. When I run gdb:
GNU gdb (GDB) 7.7.50.20140303-cvs
<snip>
This GDB was configured as "i686-pc-mingw32".
<snip>
(gdb) break main
(gdb) Breakpoint 1 at 0x40267b: file app.c, line 28.
(gdb) run
(gdb) Starting program: C:\_d\aaa\pd\src\dll\pathological\app.exe
[New Thread 1428.0x2528]
Breakpoint 1, main (argc=1, argv=0x9b2f70) at app.c:28
28 dostuff();
(gdb) info share
(gdb) From To Syms Read Shared Object Library
0x774e0000 0x77644ccc Yes (*) C:\Windows\SysWOW64\ntdll.dll
0x753d0000 0x754cadec Yes (*) C:\Windows\syswow64\kernel32.dll
0x75ea1000 0x75ee6a3a Yes (*) C:\Windows\syswow64\KernelBase.dll
0x64081000 0x6408a1d8 Yes C:\_d\aaa\pd\src\dll\pathological\hello_dll.dll
0x75041000 0x750eb2c4 Yes (*) C:\Windows\syswow64\msvcrt.dll
(*): Shared library is missing debugging information.
(gdb) A debugging session is active.
(gdb) c
Continuing.
Hello dll. <--- The function in hello_dll.dll prints this.
Program received signal SIGSEGV, Segmentation fault.
0x8000004c in ?? () <----- call to FT_GetLibraryVersion()
(gdb) bt
#0 0x8000004c in ?? ()
#1 0x0040158e in dostuff () at app.c:49
#2 0x00402680 in main (argc=1, argv=0x8e2f70) at app.c:28
(gdb)
It links with the lib without complaint but when I run the exe it (silently) doesn't load the dll.
Anybody have any ideas? Is there some linker control that I am missing? Are there other diagnostic or debug tools to dig into this further?
:::::::::::::::::::::::
edit 7/11/20
I'll post some code. (If I know how. I'm new here.)
It should be shown in the "info share", but it isn't, as you can see above.
I'm suspecting name decoration. Objdump -x of the .exe shows an entry for FTD2XX.dll in the Import Tables. But it doesn't show any vma or bound name under it. I suspect that at program load the loader sees no vma/name and decides it doesn't really need to load the dll.
There is an import table in .idata at 0x406000
<snip>
The Import Tables (interpreted .idata section contents)
vma: Hint Time Forward DLL First
Table Stamp Chain Name Thunk
00006000 0000607c 00000000 00000000 00006218 0000614c
DLL Name: FTD2XX.dll
vma: Hint/Ord Member-Name Bound-To
<----- empty?
00006014 00006080 00000000 00000000 000064f8 00006150
DLL Name: hello_dll.dll
vma: Hint/Ord Member-Name Bound-To
6224 1 hello_dll
00006028 00006088 00000000 00000000 00006554 00006158
DLL Name: KERNEL32.dll
vma: Hint/Ord Member-Name Bound-To
6230 277 DeleteCriticalSection
6248 310 EnterCriticalSection
<snip>
:::::::::::::::::::::::::::::::::::::::::::::
edit 2, 7/11/20
This is the program that calls functions in the DLLs.
/* app.c
Demonstrates using the function imported from the DLL.
*/
// 200708 pathological case. Based on the simple hello_dll.
//#include <stdlib.h>
// for sleep
#include <unistd.h>
#include <stdio.h>
// for dword
#include <windef.h>
// for lpoverlapped
#include <minwinbase.h>
#include "hello_dll.h"
// My legacy app, and really all others too, use 2.04.06.h
#include "ftd2xx_2.04.06.h"
//#include "ftd2xx_2.02.04.h"
///////////////////////////
void dostuff( void );
void call_ft_listdevices( void );
///////////////////////////
int main(int argc, char** argv)
{
FT_STATUS status;
DWORD libver;
//dostuff();
printf( "Calling hello_dll():\n" );
fflush( stdout );
hello_dll();
fflush( stdout );
printf( "Back from hello_dll()\n" );
fflush( stdout );
sleep( 1 );
printf( "Calling FT_GetLibraryVersion().\n" );
fflush( stdout );
status = FT_GetLibraryVersion( &libver );
if( status == FT_OK ){
printf( "FTD2XX library version 0x%lx\n", libver );
fflush( stdout );
}
else{
printf( "Error reading FTD2XX library version.\n" );
fflush( stdout );
}
// 200710 Adding call to different ft function did
// not result in entries in the import table.
//call_ft_listdevices( );
return 0;
}
I don't think there is a need to include the code for my hello_dll. It works.
I have three versions of the FTD2XX. I'm pretty careful about tracking versions. Plus, when one is beating one's head against the wall, double checking the versions appeals early on as a way to end the pain.
I found a surprise copy of FTD2XX.dll. It's in c:/Windows/SysWOW64. It is the oldest of the three versions I have. Versions of my app that were compiled before this problem started run correctly using that dll in that place.
Solved.
There's a bug in the 2.34.50.20200227 i686-w64-mingw32-ld.exe. It won't work with ftd2xx.lib, regardless of ftd2xx version as far as I can tell.
2.25.51.20150320 and 2.29.1.20171006 work with ftd2xx.lib. I've reverted back to 2.29 mingw64-i686-binutils. I'm running again.

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.

gdb can not `next` over an non system dll function call

The problem is with the debugging code that has a call to some dll function, this one and others from the same dll:
EdsGetCameraList(&l);
when I break on this line and then issue a next command, I get a
(gdb) n
0x1000e620 in ?? ()
0x1000e620 is address of EdsGetCameraList:
(gdb) disas find_cam,+20
Dump of assembler code from 0x401783 to 0x401797:
0x00401783 <find_cam+0>: push ebp
0x00401784 <find_cam+1>: mov ebp,esp
0x00401786 <find_cam+3>: sub esp,0x48
=> 0x00401789 <find_cam+6>: lea eax,[ebp-0x14]
0x0040178c <find_cam+9>: mov DWORD PTR [esp],eax
0x0040178f <find_cam+12>: mov eax,ds:0x4092dc
0x00401794 <find_cam+17>: call eax
0x00401796 <find_cam+19>: sub esp,0x4
End of assembler dump.
(gdb) x 0x4092dc
0x4092dc <_imp__EdsGetCameraList#4>: 0x1000e620
No wonder if I type next again I get:
(gdb) n
Cannot find bounds of current function
What is going on?
next steps over source lines - you need the debug information for the dll you're debugging if you want to do source line stepping. In this case there is no debug info available and gdb doesn't know where source lines start/end -- next won't do anything.
Instead you'll need to use the instruction-level step commands, nexti and stepi (ni, si) to single instruction step through these routines. You can also use finish to return to the caller function.
When people debug with gdb at this level, they often have gdb display the next few instructions as they step -- do disp/3i $pc to have the next three instructions displayed.

GDB script to trace Objective-C calls on iOS device - issue

I have a gdb script I am working on to trace all objective-C method calls that pass through objc_msgSend but Ive encountered a problem I cant seem to deal with. After review of the Objective-C runtime source code I have developed the following script to print [ ] at each break on objc_msgSend. The issue is that there are situations in which data_NEVER_USE is not a valid pointer but is also not null. The only indicator that I can find of whether a class is initialized is in id->data_NEVER_USE->flags & RW_REALIZED. What aspect of class initialization am I missing here that would allow me to skip this case?
b objc_msgSend
c
commands
silent
if (*$r0 == 0)
continue
end
set $id = (class_t *)$r0
set $sel = $r1
print *$id
if($id->data_NEVER_USE != 0)
set $data = (class_ro_t *) ($id->data_NEVER_USE)
if (($data->flags & 0x80000000) && ($data->name))
set $classname = $data->name
printf "[%s ", $classname
else
continue
end
end
if ($sel != 0)
printf "%s", $sel
else
printf "null"
end
printf "]\n"
continue
end
I appreciate any help on this. Thanks.
These 2 methods have worked reasonably well for me. Note that in my example I am manually starting "SomeApp" in order to monitor it as soon as it starts up.
gdb
(gdb) attach --waitfor 'SomeApp'
**this is where you manually start SomeApp on your device**
call (void)instrumentObjcMessageSends(YES)
The "instrumentObjcMessageSends" enables/disables message logging from within the runtime. Here's some more information on this method.
Another option, again still using GDB on your iDevice, is to write a small command like this:
FooPad:~ root# gdb
(gdb) attach SBSettings
Attaching to process 440.
Reading symbols for shared libraries . done
Reading symbols for shared libraries ............................. done
0x35686004 in mach_msg_trap ()
(gdb) break objc_msgSend
Breakpoint 1 at 0x3323ef72
(gdb) commands
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>printf "-[%s %s]\n", (char *)class_getName(*(long *)$r0,$r1),$r1
>c
>end
(gdb) c
Continuing.
// a ton of information will follow
As soon as you press "c" (right above line that reads "Continuing.", your screen will fill with function names and arguments.
And finally follow these instructions to get a working GDB on your iDevice. For posterity I'll post the short instructions here:
GNU Debugger (gdb) is used to analyze the run time behavior of an iOS
application. In recent iOS versions, GNU Debugger directly downloaded
from the Cydia is broken and not functioning properly. Following the
Pod 2g blog post also did not help me.
To get rid of this problem, add http://cydia.radare.org to cydia
source and download the latest GNU Debugger (build 1708). GDB build
1708 is working for iOS 5.x.

How to print disassembly registers in the Xcode console

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).