Forum: PC-Programmierung ARM image in QEMU starten


von Olli Z. (z80freak)


Lesenswert?

Ich versuche gerade ein Image eines Flash-Speichers (32MB) für einen 
ARM9 Prozessor (ARM926EJ-S) in QEMU unter Windows zum "laufen" zu 
bringen. Konkreter gesagt möchte ich da drin debuggen. Dabei hoffe ich 
auf etwas Hilfe von erfahrenen QEMU-Anwendern hier :-)

Mir ist schon klar das dies nicht einfach wird, da die ARM-Umgebungen ja 
nicht genormt sind und jeder da sein eigenes Süppchen kocht.

Soweit ich das in der Doku verstanden habe ist die "qemu-system-arm.exe" 
der zu verwendende Emulator. Dieser kennt zahlreiche "machine" (-machine 
help) und "cpu" (-cpu help) typen.

Wie gehe ich an die Sache ran, auch im Hinblick eines Debuggings? Kommt 
dafür gdb unter Windows (mingw) in Frage? Und wie "verheirate" ich das 
alles, das ich breakpoints setzen kann, etc. Laut QEMU-Doku soll man die 
Programmausführung mit "-s" verhindern können, sodass man quasi vom 
RESET-Zeitpunkt an debuggen kann.

Danke für die Hilfe

: Bearbeitet durch User
von Vincent H. (vinci)


Lesenswert?

Das ist im Prinzip gar nicht soooo schwierig. Es gibt nur leider recht 
wenige Beispiele im Netz dazu. Ich hab vor kurzem mal ein Cortex M3 
Projekt in QEMU gedebugged und dabei folgende Aufrufe genutzt:

Starten von QEMU, ohne graphische Ausgabe, Semihosting ein und GDB auf 
1234:
1
qemu-system-arm
2
-cpu cortex-m3
3
-machine lm3s6965evb
4
-nographic
5
-semihosting-config enable=on,target=native 
6
-gdb tcp::1234 
7
-S -kernel test.elf

Starten von GDB auf 1234:
1
gdb file test.elf
2
target remote :1234
3
thb main

von Olli Z. (z80freak)


Lesenswert?

Dankeschön :-)

Mein image ist jedoch nicht im ELF-format und der GDB meckert mir das an 
("... is not a core dump: file format not recognized").

Wenn ich ich QEMU so starte (in einer CMD-Shell) dann passiert einfach 
NICHTS. Sprich das Kommando geht zurück und nichts wurde gestartet. 
Hmmm...

c:\Programme\qemu\qemu-system-arm.exe -machine n800 -nographic 
-semihosting-config enable=on,target=native -gdb tcp:1234 -S -kernel 
"D:\Temp\FX_8M5T-18K931-HD_7612300566_MBFLASH_PIN-8075.bin"

Dieses File hat auch keine Symbole, zumindest nicht das ich wüsste 
(müsste man doch auch irgendwie rauskriegen? Ein einfacher "readelf" 
bring nur "readelf: Error: Not an ELF file - it has the wrong magic 
bytes at the start"). Es startet einfach ab 0x0000 mit ARM-Code.

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Olli Z. schrieb:
> Es startet einfach ab 0x0000 mit ARM-Code.

Im Zweifelsfall kann man daraus ein ELF machen, indem man es via objcopy 
konvertiert und dann linkt; im Linkerscript muss man die Startadresse 
einstellen.

Olli Z. schrieb:
> Dieses File hat auch keine Symbole, zumindest nicht das ich wüsste

Kann es auch nicht haben, wenn es kein ELF/COFF/PE o.ä. ist, was nicht 
der Fall ist, wenn es einfach nur ARM-Code ist!

Olli Z. schrieb:
> Es startet einfach ab 0x0000 mit ARM-Code.

von Olli Z. (z80freak)


Lesenswert?

Niklas G. schrieb:
> Im Zweifelsfall kann man daraus ein ELF machen, indem man es via objcopy
> konvertiert und dann linkt; im Linkerscript muss man die Startadresse
> einstellen.
Ok, ich habe nun mit
1
objcopy.exe --input-target=binary --output-target=elf32-little C:\temp\FX_8M5T-18K931-HD_7612300566_MBFLASH_PIN-8075.bin C:\temp\FX_8M5T-18K931-HD_7612300566_MBFLASH_PIN-8075.elf

ein ELF erzeugt. Schaue ich mir das mit
1
readelf.exe -a C:\temp\FX_8M5T-18K931-HD_7612300566_MBFLASH_PIN-8075.elf
 an erhalte ich
1
ELF Header:
2
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
3
  Class:                             ELF32
4
  Data:                              2's complement, little endian
5
  Version:                           1 (current)
6
  OS/ABI:                            UNIX - System V
7
  ABI Version:                       0
8
  Type:                              REL (Relocatable file)
9
  Machine:                           None
10
  Version:                           0x1
11
  Entry point address:               0x0
12
  Start of program headers:          0 (bytes into file)
13
  Start of section headers:          33555012 (bytes into file)
14
  Flags:                             0x0
15
  Size of this header:               52 (bytes)
16
  Size of program headers:           0 (bytes)
17
  Number of program headers:         0
18
  Size of section headers:           40 (bytes)
19
  Number of section headers:         5
20
  Section header string table index: 4
21
22
Section Headers:
23
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
24
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
25
  [ 1] .data             PROGBITS        00000000 000034 2000000 00  WA  0   0  1
26
  [ 2] .symtab           SYMTAB          00000000 2000034 000050 10      3   2  4
27
  [ 3] .strtab           STRTAB          00000000 2000084 00019c 00      0   0  1
28
  [ 4] .shstrtab         STRTAB          00000000 2000220 000021 00      0   0  1
29
Key to Flags:
30
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
31
  L (link order), O (extra OS processing required), G (group), T (TLS),
32
  C (compressed), x (unknown), o (OS specific), E (exclude),
33
  p (processor specific)
34
35
There are no section groups in this file.
36
37
There are no program headers in this file.
38
39
There are no relocations in this file.
40
41
The decoding of unwind sections for machine type None is not currently supported.
42
43
Symbol table '.symtab' contains 5 entries:
44
   Num:    Value  Size Type    Bind   Vis      Ndx Name
45
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
46
     1: 00000000     0 SECTION LOCAL  DEFAULT    1
47
     2: 00000000     0 NOTYPE  GLOBAL DEFAULT    1 _binary_D__Cloudstore_ION
48
     3: 02000000     0 NOTYPE  GLOBAL DEFAULT    1 _binary_D__Cloudstore_ION
49
     4: 02000000     0 NOTYPE  GLOBAL DEFAULT  ABS _binary_D__Cloudstore_ION
50
51
No version information found in this file.

Sieht ja eigentlich gut aus, oder?
Was meinst Du nun mit dem "Linker script"?

: Bearbeitet durch User
von Olli Z. (z80freak)


Lesenswert?

Vincent H. schrieb:

> qemu-system-arm
> -cpu cortex-m3
> -machine lm3s6965evb
> -nographic
> -semihosting-config enable=on,target=native
> -gdb tcp::1234
> -S -kernel test.elf

Das führt bei mir dazu das offenbar nichts gestartet wird. Der Aufruf 
erfolgt, aber anschließend wird kein QEMU geöffnet, bzw. ist gleich 
wieder beendet (kann ich nicht erkennen).

Ich rufe das so auf (den n800 habe ich nur genommen weil da ein ARM926EJ 
Prozessor drin ist):
1
c:\Programme\qemu\qemu-system-arm.exe -machine n800 -gdb tcp::1234 -nographic -S -semihosting-config enable=on,target=native -kernel "D:\temp\FX_8075.elf"

Eigentlich müsste nun ja QEMU starten, das ELF lesen und einen Listener 
auf dem Port 1234 starten auf den sich dann im Nachgang der GDB 
connecten würde, richtig?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Olli Z. schrieb:
> ein ELF erzeugt.

Das ist dann aber vermutlich ein x86 ELF :) Mache das so um ein ARM-ELF 
zu erhalten, und die Section-Flags zu setzen:
1
arm-none-eabi-objcopy -I binary -O elf32-littlearm -B arm --rename-section .data=.text --set-section-flags .text=alloc,code image.bin image.o

Olli Z. schrieb:
> Sieht ja eigentlich gut aus, oder?

Ja, aber das ist noch ein relokierbares Image ohne Adressen, d.h. QEMU 
wüsste nicht wo das in den Speicher hin soll. Lege daher ein simples 
Linker-Script an, z.B. in der Datei "image.ld":
1
ENTRY(Reset_Handler)
2
3
SECTIONS
4
{
5
  .text 0x80000000 : {
6
    Reset_Handler = .;
7
    *.(text)
8
  }
9
}

Wichtig ist hier, die Adresse des RAM zu setzen, gegen welche 
hoffentlich der Code im Binary gelinkt wurde (sonst funktionieren keine 
Sprünge). Als Entry-Point wird hier die allererste Adresse im Code 
gesetzt. Ist das korrekt? Wenn am Anfang des Images noch eine 
Exception-Tabelle oder so steht wäre es ggf. sinnvoll "Reset_Handler = 
(. + 0x20);" oder so zu setzen. Weiß aber nicht ob QEMU das überhaupt 
auswertet.

Danach kannst du das so linken:
1
arm-none-eabi-ld -T image.ld image.o -o image.elf

Das sollte dann ein korrektes ELF mit einer einzelnen binären Section 
ergeben.

Ich habe bei mir testweise als image.bin eine Textdatei mit "Hallo!" 
angelegt. Das ergibt:
1
$ readelf -S image.o
2
There are 5 section headers, starting at offset 0xf4:
3
4
Section Headers:
5
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
6
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
7
  [ 1] .text             PROGBITS        00000000 000034 000007 00  WA  0   0  1
8
  [ 2] .symtab           SYMTAB          00000000 00003c 000050 10      3   2  4
9
  [ 3] .strtab           STRTAB          00000000 00008c 000046 00      0   0  1
10
  [ 4] .shstrtab         STRTAB          00000000 0000d2 000021 00      0   0  1
1
$ readelf -S image.elf
2
There are 5 section headers, starting at offset 0x100f0:
3
4
Section Headers:
5
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
6
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
7
  [ 1] .text             PROGBITS        80000000 010000 000007 00  AX  0   0  1
8
  [ 2] .symtab           SYMTAB          00000000 010008 000070 10      3   3  4
9
  [ 3] .strtab           STRTAB          00000000 010078 000057 00      0   0  1
10
  [ 4] .shstrtab         STRTAB          00000000 0100cf 000021 00      0   0  1
1
$ arm-none-eabi-objdump -s -j .text image.elf 
2
3
image.elf:     file format elf32-littlearm
4
5
Contents of section .text:
6
 80000000 48616c6c 6f210a                      Hallo!.
1
$ arm-none-eabi-nm image.elf
2
80000007 T _binary_image_bin_end
3
00000007 A _binary_image_bin_size
4
80000000 T _binary_image_bin_start
5
80000000 T Reset_Handler

Man beachte die Adresse 80000000 und die Flags "AX" und das "PROGBITS".

von Olli Z. (z80freak)


Lesenswert?

Niklas G. schrieb:
> wüsste nicht wo das in den Speicher hin soll. Lege daher ein simples 
Linker-Script an

Ok, verstanden! :-)

> Wichtig ist hier, die Adresse des RAM zu setzen, gegen welche
> hoffentlich der Code im Binary gelinkt wurde (sonst funktionieren keine 
Sprünge).
Ah, ok, klar. Ja das System hat RAM und zwar einmal 64 Kbyte internes 
SRAM ab Adresse 0x2000 0000 - 0x2000 FFFF und einmal 128 MByte externes 
SD-RAM ab Adresse 0x8000 0000.

> Wenn am Anfang des Images noch eine Exception-Tabelle oder so steht
Ja, da ist der ARM Typische Block mit 0x20 Bytes, von denen aber nur der 
Reset-Vector sinnvoll belegt ist, alle anderen führen zu einer 
Endlosschleife. Der Reset springt dann zu 0xD1C. Dort beginnt eine 
Initialisierung. Genau da möchte ich mit dem Debugging beginnen :-)
Also müsste ich dann im Linkerfile den "Reset_Handler = (. + 0xD1C);" 
setzen?

> Danach kannst du das so linken:
Ok, teste ich.

> Ich habe bei mir testweise als image.bin eine Textdatei mit "Hallo!"
Ich kann auch gern die Daten hier bereitstellen, stehen in einem anderen 
Thread von mir eh zum Download 
https://www.mikrocontroller.net/attachment/423482/8S7T-18K931-AD_7612300524_PIN-8367.zip

Die ARM-spezifischen tools wie "arm-none-eabi-ld" habe ich in meiner 
MinGW-Umgebung nicht drin. Mit welchem Paket erhalte ich die?

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Angehängte Dateien:

Lesenswert?

Olli Z. schrieb:
> Ah, ok, klar. Ja das System hat RAM und zwar einmal 64 Kbyte internes
> SRAM ab Adresse 0x2000 0000 - 0x2000 FFFF und einmal 128 MByte externes
> SD-RAM ab Adresse 0x8000 0000.

Ok, muss man die beide belegen? Dann müsste man das Image auftrennen...

Olli Z. schrieb:
> Also müsste ich dann im Linkerfile den "Reset_Handler = (. + 0xD1C);"
> setzen?

Ist gar nicht nötig, die Einträge sind bei den ARM926 genau wie beim 
ARMv7A (und im Unterschied zum Cortex-M) einfach nur 
Sprung-Instruktionen ("B" oder "LDR"). Dann kannst du es so lassen, dann 
springt es ja automatisch ans richtige Ziel. Ist sogar besser, dann 
funktioniert es auch wenn sich die Adresse mal ändert.

Olli Z. schrieb:
> Mit welchem Paket erhalte ich die?

Da z.B.:
https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-eabi/

Die für Cortex-M sollten aber auch gehen:
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm

Vielleicht wertet QEMU die Architektur-Header auch gar nicht aus, dann 
wäre es egal... Habe dein Image mal entsprechend zu einem ELF umgebaut 
und angehängt.

Wenn du das Image aber selbst erstellt hast - wieso hast du dann nicht 
sowieso schon eine ELF-Datei die beim Kompilieren & Linken hinten raus 
fällt? Das wäre doch deutlich netter, dann hast du Funktionsnamen und 
Debug-Symbole...

von Olli Z. (z80freak)


Lesenswert?

OKAY! Das klappt nun. Was etwas fizzelig an dieses linaro-Paket zu 
kommen, bzw. es zu installieren. Letztlich musste ich erst über 
"mingw-get" das "xz"-Tool runterladen, dann das linaro-Archiv (.xz 
Datei), dieses in den C:\mingw\ Ordner werfen und mit "xz -xvf 
gcc-linaro-7.4.1-2019.02-i686-mingw32_arm-eabi.tar.xz" entpacken damit 
die Dateien an die richtigen Stellen kommen.

Nun habe ich das korrekte ELF und damit startet dann auch der QEMU wie 
es Vincent oben geschrieben hat. Habe den Befehl eine eine Windows-Batch 
geschrieben:

C:\Programme\qemu\qemu-system-arm.exe -machine n800 -gdb tcp::1234 
-nographic -S -semihosting-config enable=on,target=native -kernel 
"C:\temp\image.elf"

Anschließend kann ich in einer CMD-Shell den GDB starten:

gdb C:\temp\image.elf

(das "file" zwischen gdb und Dateiname musste ich weglassen damit es 
funktioniert)

Und dann konnte ich im gdb mit "target remote :1234" verbinden.
1
C:\temp>gdb image.elf
2
GNU gdb (GDB) 7.6.1
3
Copyright (C) 2013 Free Software Foundation, Inc.
4
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
5
This is free software: you are free to change and redistribute it.
6
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
7
and "show warranty" for details.
8
This GDB was configured as "mingw32".
9
For bug reporting instructions, please see:
10
<http://www.gnu.org/software/gdb/bugs/>...
11
Reading symbols from C:\temp\image.elf...(no debugging symbols found)...done.
12
(gdb) target remote :1234
13
Remote debugging using :1234
14
warning: while parsing target description (at line 1): Target description specified unknown architecture "arm"
15
warning: Could not load XML target description; ignoring
16
0x00000000 in ?? ()
17
(gdb)

Allerdings kennt das ELF kein "main":

(gdb) thb main
Function "main" not defined.

: Bearbeitet durch User
von Niklas Gürtler (Gast)


Lesenswert?

Olli Z. schrieb:
> Allerdings kennt das ELF kein "main"

Natürlich nicht. In der bin Datei sind keine Symbole, und das einbetten 
in eine ELF Datei fügt die nicht hinzu. Du musst alles auf Basis von 
Adressen und Assembler machen. Wie gesagt - beim selbst kompilieren 
müsste eine ELF Datei mit Symbolen herauskommen. Man muss nur den Umweg 
über die bin Datei vermeiden!

von Kai S. (zigzeg)


Lesenswert?

Das Debuggen mit gdb wird ziemlich mühsam werden, da eine Menge Dinge 
fehlen die man normalerweise hat:
- keine Funktionsnamen, nur Adressen
- kein Stack, mit etwas Glück einen Level (die aufrufende Funktion, bei 
ARM im LR register)
- keine Variablen

Vielleicht wäre ein Tool wie radare2, ghidra or IDA Pro eine bessere 
Wahl?

von Olli Z. (z80freak)


Lesenswert?

Danke, das ist mir schon alles klar. Leider habe ich nichts und ich 
wollte bewusst auf Assembler Ebene debuggen.

IDA Pro hätte ich zur Verfügung, aber damit habe ich bislang nur etwas 
"offline" disassembliert. Es gibt aber Dinge die man nur mit breakpoints 
entdecken kann.

von Bernd K. (prof7bit)


Lesenswert?

Olli Z. schrieb:
> Die ARM-spezifischen tools wie "arm-none-eabi-ld" habe ich in meiner
> MinGW-Umgebung nicht drin. Mit welchem Paket erhalte ich die?

Mit der Installation der Compiler Toolchain von ARM: 
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads

von Niklas Gürtler (Gast)


Lesenswert?

Wo kommt das .bin  Image denn her? Wenn du die Adressen von Funktionen 
und Variablen kennst, kannst du die ins Linker Script schreiben:
1
main = 0x80001234;
2
buttonpressed = 0x80002000;
Dann sieht der Debugger die.

Also wenn man z.B. den Linux Kernel kompiliert, erhält man ein binäres 
Abbild des Speichers ("zImage"), wie er beim starten aussehen sollte. Da 
sind dann normalerweise keine Debug Infos und Symbole drin. Zuvor wird 
allerdings eine ELF Datei angelegt ("vmlinux"), in welcher alle Symbole 
drin sind. Diese kann man zwar nicht mit jedem Bootloader starten, aber 
man kann sie in den GDB und vermutlich auch QEMU laden, um dann 
komfortabel Debuggen zu können. Geht sowas bei dir nicht?

von Olli Z. (z80freak)


Lesenswert?

Niklas Gürtler schrieb:
> Wo kommt das .bin  Image denn her? Wenn du die Adressen von Funktionen
Das ist ein JTAG-Dump eines Flash-Speichers. Und ich gehe mal davon aus 
das die Ursprünglichen Entwickler (einen könnte ich fragen, aber der 
darf nix sagen, NDA) im Jahre 2005 oder wann das war, auch schon so 
schlau waren keine Debug-Symbole oder sonstige Infos ins BIN zu packen. 
Im Image (welches ich ja oben verlinkt habe, kann sich jeder selbst gern 
anschauen) finden sich zwar zahlreiche Debug-Meldungen, aber das ist ja 
eine andere "Ebene".

> und Variablen kennst, kannst du die ins Linker Script schreiben:
>
1
main = 0x80001234;
2
> buttonpressed = 0x80002000;
> Dann sieht der Debugger die.
Interessant, das wäre eine Option. Derzeit mache ich das über IDA Pro im 
disassemblierten ARM code. An einigen Stellen komme ich aber durch 
reines lesen nicht weiter und müsste mal sehen wie sich das im 
LIVE-Umfeld verhält.

Eine Idee war eben das Image über einen QEMU schrittweise ausführen zu 
lassen. So könnten mir auch Leute helfen die selbst kein solches Gerät 
zur Verfügung haben :-)

Eine andere wäre es das im Gerät zu tun, mit dem Segger JTAG Debugger.

> Also wenn man z.B. den Linux Kernel kompiliert, erhält man ein binäres
> Abbild des Speichers ("zImage"), wie er beim starten aussehen sollte. Da
> sind dann normalerweise keine Debug Infos und Symbole drin. Zuvor wird
> allerdings eine ELF Datei angelegt ("vmlinux"), in welcher alle Symbole
> drin sind. Diese kann man zwar nicht mit jedem Bootloader starten, aber
> man kann sie in den GDB und vermutlich auch QEMU laden, um dann
> komfortabel Debuggen zu können. Geht sowas bei dir nicht?
Danke für die Erklärung, so langsam verstehe ich das dadurch. Äh, nein, 
bei meinem BIN image kann ich im moment noch garnichts machen, nichtmal 
schrittweise ausführen lassen, keine Speicher auslesen, keine Register 
anzeigen. Irgendwas stimmt also noch nicht...

von Olli Z. (z80freak)


Lesenswert?

Ich habe noch dieses interessante Dokument gefunden: 
https://www.hex-rays.com/products/ida/support/tutorials/debugging_qemu.pdf

Darin geht es um die Instrumentation von QEMU von IDA aus, um 
"Codesnippets" ausführen zu können. Also genau was ich suche. Das 
probiere ich nun mal aus, ob ich da weiter komme.

So wie ich es sehe kann man mit IDA durchaus direkt debuggen. Eine 
möglichkeit ist es wohl dies über einen Debug-Server zu tun. Helft mir 
mal ob ich das richtig verstanden hab:
----

Der Debug-Server kann z.B. ein im Netzwerk befindliches "J-Link ARM" 
Interface sein. Der Adapter spricht dann auf der Hardware-Seite via 
JTAG/SWD mit dem ICE des Chips und auf der Softwareseite mit dem 
Debugger in IDA.

Oder der Debug-Server wird als Prozess auf dem Remote-System gestartet 
in dem auch die zu debuggende Software läuft, bzw. ausgeführt werden 
kann. Das kommt wohl gerne bei Linux oder Windows-Betriebssystemen zum 
Einsatz.

Die Schwierigkeit in einer proprietären Umgebung wie meinem Board ist es 
wohl das man wenig Möglichkeit hat darin einen Debugger zu starten, 
daher wäre eine externe Hardware-Lösung schon das Mittel der Wahl für 
ein "In-Circuit-Debugging".

----

Überhaupt muss man immer aufpassen das man beim Thema ARM-Debugging 
nicht in einer Linux-Welt landet, sondern schön in seiner SoC-Umgebung 
bleibt.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Olli Z. schrieb:
> Das ist ein JTAG-Dump eines Flash-Speichers. Und ich gehe mal davon aus
> das die Ursprünglichen Entwickler (einen könnte ich fragen, aber der
> darf nix sagen, NDA)

Sag das doch früher...

Olli Z. schrieb:
> keine Debug-Symbole oder sonstige Infos ins BIN zu packen.

Wie denn auch; der ausführende Prozessor kann mit Debug-Symbolen nichts 
anfangen, daher werden die im Speicher nicht gebraucht, daher gibt es 
kein Format mit dem die Symbole in einem Speicherabbild abgelegt werden 
können. Theoretisch könnte man die entsprechenden ELF-Sections in einen 
nicht genutzten Bereich legen, aber das ist mehr als unüblich...

Olli Z. schrieb:
> Derzeit mache ich das über IDA Pro im
> disassemblierten ARM code.

Und IDA merkt sich die von dir annotierten Funktionsnamen? Das ist doch 
auch gut, wenn du das ins Linkerscript exportierst wäre es im ELF 
"persistent" auch für andere Tools.

Olli Z. schrieb:
> nichtmal
> schrittweise ausführen lassen, keine Speicher auslesen, keine Register
> anzeigen. Irgendwas stimmt also noch nicht...

Kannst du es nicht mal mit einem Beispiel-Image für QEMU ausprobieren? 
Eines das nur aus NOPs besteht? Oder besser noch - ein "normal" via GCC 
kompiliertes & gelinktes ELF, mit allen (Debug-)Symbolen.

Olli Z. schrieb:
> Der Debug-Server kann z.B. ein im Netzwerk befindliches "J-Link ARM"
> Interface sein

Oder per USB angeschlossen, und auf dem PC läuft der JLinkGDBServer...

Olli Z. schrieb:
> Überhaupt muss man immer aufpassen das man beim Thema ARM-Debugging
> nicht in einer Linux-Welt landet, sondern schön in seiner SoC-Umgebung
> bleibt.

Na, was für ein OS ist das denn? Linux ist hier ja praktisch 
De-Facto-Standard.

: Bearbeitet durch User
von Olli Z. (z80freak)


Lesenswert?

Also, ich habe die grundlegende Funktionalität gefunden. In der 
cfg/dbg_arch.cfg von IDA wird der Pfad zum QEMU über eine Variable 
gesetzt. Default ist %ProgramFiles%/QEMU, was bei mir passte.
Dann geht man in IDA in die "Debugger options...", dort auf "Set 
Specific Options", "Choose a configuration" und wählt "ARM_versatilepb". 
Die restlichen Settings sind interessant, aber für den Anfang reicht 
das.

Nun startet man den Debugger, dieser startet QEMU und man kann 
schrittweise ausführen, Breakpoints setzen, etc. :-)

Also nächstes würde ich versuchen die Memory Map des Gerätes dort 
abzubilden, damit die Speicherzugriffe grundsätzlich funktionieren.

Was natürlich nicht geht ist die Abbildung der SoC memory mapped 
ports...

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Olli Z. schrieb:
> Was natürlich nicht geht ist die Abbildung der SoC memory mapped
> ports...

Hat QEMU gar keine Unterstützung für den spezifischen SoC? Hoffentlich 
greift dein Kernel nicht gleich in den ersten 7 Instruktionen auf 
SoC-spezifische Hardware zu - selbst der ARM-Kern ist ja konfigurierbar, 
und je nachdem ob der Code eine bestimmte Konfiguration annimmt oder 
generisch ist (wie Linux) kann der auch ziemlichen Unsinn machen...

Ist letztlich eine Frage wie früh der Code crasht :)

: Bearbeitet durch User
von Olli Z. (z80freak)


Lesenswert?

Na klar ist der SoC anders als ein reiner ARM. Der OMAP5912 hat ja noch 
nen DSP und internes SRAM und ROM und jede Menge IO-Kram.
Ich wüsste garnicht wie man das "in software" nachbilden sollte.
Aber ich würde einfach mal sehen wie weit ich komme.
In der Init-Sequenz werden bestimmte über Speicheradressen verfügbare 
Peripheriebausteine initialisiert und teilweise auch abgefragt. Hier 
gibt es schon erste Endlosschleifen weil dort auf einen bestimmten 
Zustand gewartet wird. Diese Adresse liegen irgendwo bei 0xFFFE 0000 
aufwärts bis 0xFFFF FFFF.

D.H. wenn ich diesen Teil als RAM definiere dann müsste ich doch 
innerhalb der Debugger-Sitzung die abgefragte Speicherstelle ändern 
können sodass es weiter geht, oder ich überspringe die Loop einfach.

Naja "in-circuit" wäre definitiv besser :-) Aber dazu brauche ich einen 
J-Link ARM.

von Olli Z. (z80freak)


Lesenswert?

IDA baut beim o.g. Setup selbst eine temporäre ELF-Datei. Tja, die 
kochen halt auch nur mit Wasser ;-)

Ich habe versucht noch etwas mehr über die gdb_arch.cfg herauszufinden. 
Der per Default vorhandene ARM-Eintrag sieht ja so aus:
1
.ARM_versatilepb
2
name       QEMU: ARM Versatile/PB
3
cpu        arm
4
range      DATA RAM     0x00000000:0x08000000
5
range      IO   SYSREGS 0x10000000:0x10200000
6
initial_sp 0x08000000
7
8
; %i - input file from "Process Options" dialog
9
; %e - temporary ELF file created from database contents
10
; %p - port number
11
12
cmdline    "$(QEMUPATH)/qemu-system-arm" $(QEMUFLAGS) -kernel "%e" -M versatilepb -cpu cortex-a8

Die MACHINE "versatilepb" ist ja gut (ARM Versatile/PB (ARM926EJ-S)), 
nur die CPU stimmt doch nicht. Der OMAP5912 hat eine ARM926EJ-S CPU (so 
wie in der "machine" eigentlich vorgesehen) und da sollte dann doch 
besser "-cpu arm926" stehen, oder?

Und dann kommen die IDA-Parameter zur Memory-Map. Die passt auch nicht 
zu meinem OMAP. Wo finde ich denn eine Übersicht der für "range" 
gültigen Schlüsselwörter und wie geht IDA damit um?

Die Memory-Map die ich bislang ermittelt habe müsste so aussehen:
1
0x0000 0000 - 0x01FF FFFF = 32 MB External Flash
2
0x2000 0000 - 0x2000 FFFF = internal SRAM of OMAP
3
0x8000 0000 - 0xEFFF FFFF = external SDRAM
4
0xFFFE 0000 - 0xFFFF FFFF = Memory mapped registers

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Olli Z. schrieb:
> D.H. wenn ich diesen Teil als RAM definiere dann müsste ich doch
> innerhalb der Debugger-Sitzung die abgefragte Speicherstelle ändern
> können sodass es weiter geht, oder ich überspringe die Loop einfach.

Theoretisch ja... Aber dann z.B. DMA-Transfers oder Timer-Interrupts mit 
dem richtigen Timing zu simulieren dürfte spannend werden.

Olli Z. schrieb:
> Aber dazu brauche ich einen
> J-Link ARM.

Die Investition lohnt sich. Die 50€ für private Nutzung wären es mir 
wert die vielen grauen Haare mit QEMU zu sparen! Wenn man sich schon IDA 
leistet sind das doch Peanuts :)

Olli Z. schrieb:
> und da sollte dann doch
> besser "-cpu arm926" stehen, oder?

Vermutlich. Der Cortex-A8 ist ja schon ziemlich anders.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.