amiga-bootcamp/05_reversing/static/struct_recovery.md
Ilia Sharin fca930d0db docs(amiga): make cross-references clickable markdown links
Convert bare .md path references in 29 files to proper [name](relative/path)
markdown links for GitHub navigation.
2026-04-23 12:24:21 -04:00

137 lines
3.5 KiB
Markdown

[← Home](../../README.md) · [Reverse Engineering](../README.md)
# Recovering Data Structures
## Overview
Amiga executables use OS structures extensively — `ExecBase`, `Node`, `Process`, `IORequest`, etc. This document describes how to recover and annotate these structures in disassembly by matching field access patterns against NDK39 header offsets.
---
## The MOVE.L offset(An),Dm Pattern
Structure field accesses appear as:
```asm
MOVEA.L _DOSBase, A6
MOVE.L ($17A,A6), A0 ; SysBase->LibList at offset +0x17A
MOVE.L (A0), A1 ; lh_Head
```
The key is the **base register** and **constant offset**. Match the offset against known structure definitions.
---
## Common Structures and Key Offsets
### `struct ExecBase` (at absolute address `$4`)
| Offset | Field | Type |
|---|---|---|
| +0 | `LibNode` | `struct Library` |
| +0x128 | `TaskReady` | `struct List` |
| +0x132 | `TaskWait` | `struct List` |
| +0x17A | `LibList` | `struct List` |
| +0x182 | `DeviceList` | `struct List` |
| +0x21E | `ChipRevBits0` | `UWORD` |
| +0x280 | `MemList` | `struct List` |
### `struct Node` (8 bytes)
| Offset | Field |
|---|---|
| +0 | `ln_Succ` (next node) |
| +4 | `ln_Pred` (prev node) |
| +8 | `ln_Type` (UBYTE) |
| +9 | `ln_Pri` (BYTE priority) |
| +10 | `ln_Name` (STRPTR) |
List traversal:
```asm
MOVEA.L lh_Head, A0 ; first node
.loop:
TST.L (A0) ; ln_Succ == NULL?
BEQ.S .done
; process node at A0
MOVEA.L (A0), A0 ; A0 = ln_Succ
BRA.S .loop
```
### `struct Process` (extends `struct Task`)
| Offset | Field |
|---|---|
| +0 | `pr_Task` (struct Task) |
| +92 | `pr_MsgPort` |
| +128 | `pr_CLI` (BPTR, non-NULL if CLI) |
| +172 | `pr_SegList` (BPTR to segment list) |
Detection in disassembly:
```asm
MOVE.L ($80,A4), D0 ; pr_CLI at offset +0x80
BEQ.S .wb_launch ; NULL = Workbench
```
### `struct IORequest` / `struct IOStdReq`
| Offset | Field |
|---|---|
| +0 | `io_Message` (struct Message) |
| +20 | `io_Device` |
| +24 | `io_Unit` |
| +28 | `io_Command` (UWORD) |
| +30 | `io_Flags` (UBYTE) |
| +32 | `io_Error` (BYTE) |
| +36 | `io_Length` (ULONG) |
| +40 | `io_Actual` (ULONG) |
| +44 | `io_Data` (APTR) |
| +48 | `io_Offset` (ULONG) |
---
## Annotating Structures in IDA Pro
### Define a structure type:
1. `View → Open Subviews → Local Types``Insert` → paste C struct definition
2. IDA parses the struct and creates a type entry
3. Navigate to the base register in disassembly
4. Press `T` (structure offset) on any `offset(An)` operand
5. Select the struct type → all accesses auto-annotated
### Import NDK39 headers:
Use `File → Load file → Parse C header file` → select `exec/execbase.h`, `exec/tasks.h`, etc. from NDK39.
---
## Exec Node Traversal Loops
A recurring pattern: walking the `LibList` or `DeviceList`:
```asm
; Annotated after struct recovery:
MOVEA.L SysBase, A6
LEA (LibList,A6), A0 ; &SysBase->LibList
MOVEA.L (lh_Head,A0), A1 ; first lib node
.scan:
MOVEA.L (ln_Succ,A1), A2 ; peek next
TST.L A2
BEQ.S .not_found
; compare ln_Name string
MOVEA.L (ln_Name,A1), A0
JSR ___strcmp
TST.L D0
BEQ.S .found
MOVEA.L A2, A1
BRA.S .scan
```
---
## References
- NDK39: `exec/execbase.h`, `exec/tasks.h`, `exec/nodes.h`, `exec/io.h`
- [exec_base.md](../../06_exec_os/exec_base.md) — full ExecBase field listing
- [lists_nodes.md](../../06_exec_os/lists_nodes.md) — MinList/List traversal
- IDA Pro: Structure subview, Local Types, T hotkey for struct offset