]> git.sesse.net Git - pistorm/blob - platforms/amiga/hunk-reloc.c
[WIP] Pile of stuff
[pistorm] / platforms / amiga / hunk-reloc.c
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <endian.h>
7 #include "hunk-reloc.h"
8
9 #define DEBUG(...)
10 //#define DEBUG printf
11
12 #define READLW(a, b) fread(&a, 4, 1, b); a = be32toh(a);
13 #define READW(a, b) fread(&a, 2, 1, b); a = be16toh(a);
14
15 uint32_t lw;
16
17 char *hunk_id_name(uint32_t index) {
18     switch (index) {
19         case HUNKTYPE_HEADER:
20             return "HUNK_HEADER";
21         case HUNKTYPE_CODE:
22             return "HUNK_CODE";
23         case HUNKTYPE_HUNK_RELOC32:
24             return "HUNK_RELOC32";
25         case HUNKTYPE_SYMBOL:
26             return "HUNK_SYMBOL";
27         case HUNKTYPE_BSS:
28             return "HUNK_BSS";
29         case HUNKTYPE_DATA:
30             return "HUNK_DATA";
31         case HUNKTYPE_END:
32             return "HUNK_END";
33         default:
34             return "UNKNOWN HUNK TYPE";
35     }
36 }
37
38 int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_reloc *r) {
39     if (!f)
40         return -1;
41     
42     uint32_t discard = 0, cur_hunk = 0, offs32 = 0;
43     
44     switch (index) {
45         case HUNKTYPE_HEADER:
46             DEBUG("Processing hunk header.\n");
47             do {
48                 READLW(discard, f);
49                 if (discard) {
50                     info->libnames[info->num_libs] = malloc(discard * 4);
51                     fread(info->libnames[info->num_libs], discard, 4, f);
52                     info->num_libs++;
53                 }
54             } while (discard);
55             
56             READLW(info->table_size, f);
57             DEBUG("Table size: %d\n", info->table_size);
58             READLW(info->first_hunk, f);
59             READLW(info->last_hunk, f);
60             info->num_hunks = (info->last_hunk - info->first_hunk) + 1;
61             DEBUG("First: %d Last: %d Num: %d\n", info->first_hunk, info->last_hunk, info->num_hunks);
62             info->hunk_sizes = malloc(info->num_hunks * 4);
63             info->hunk_offsets = malloc(info->num_hunks * 4);
64             for (uint32_t i = 0; i < info->table_size; i++) {
65                 READLW(info->hunk_sizes[i], f);
66                 DEBUG("Hunk %d: %d (%.8X)\n", i, info->hunk_sizes[i] * 4, info->hunk_sizes[i] * 4);
67             }
68             return 0;
69             break;
70         case HUNKTYPE_CODE:
71             DEBUG("Hunk %d: CODE.\n", info->current_hunk);
72             READLW(discard, f);
73             info->hunk_offsets[info->current_hunk] = ftell(f);
74             DEBUG("Code hunk size: %d (%.8X)\n", discard * 4, discard * 4);
75             fseek(f, discard * 4, SEEK_CUR);
76             return 0;
77             break;
78         case HUNKTYPE_HUNK_RELOC32:
79             DEBUG("Hunk %d: RELOC32.\n", info->current_hunk);
80             DEBUG("Processing Reloc32 hunk.\n");
81             do {
82                 READLW(discard, f);
83                 if (discard) {
84                     READLW(cur_hunk, f);
85                     DEBUG("Relocating %d offsets pointing to hunk %d.\n", discard, cur_hunk);
86                     for(uint32_t i = 0; i < discard; i++) {
87                         READLW(offs32, f);
88                         DEBUG("#%d: @%.8X in hunk %d\n", i + 1, offs32, cur_hunk);
89                         r[info->reloc_hunks].offset = offs32;
90                         r[info->reloc_hunks].src_hunk = info->current_hunk;
91                         r[info->reloc_hunks].target_hunk = cur_hunk;
92                         info->reloc_hunks++;
93                     }
94                 }
95             } while(discard);
96             return 0;
97             break;
98         case HUNKTYPE_SYMBOL:
99             DEBUG("Hunk %d: SYMBOL.\n", info->current_hunk);
100             DEBUG("Processing Symbol hunk.\n");
101             READLW(discard, f);
102             do {
103                 if (discard) {
104                     char sstr[256];
105                     memset(sstr, 0x00, 256);
106                     fread(sstr, discard, 4, f);
107                     READLW(discard, f);
108                     DEBUG("Symbol: %s - %.8X\n", sstr, discard);
109                 }
110                 READLW(discard, f);
111             } while (discard);
112             return 0;
113             break;
114         case HUNKTYPE_BSS:
115             DEBUG("Hunk %d: BSS.\n", info->current_hunk);
116             READLW(discard, f);
117             info->hunk_offsets[info->current_hunk] = ftell(f);
118             DEBUG("Skipping BSS hunk. Size: %d\n", discard * 4);
119             return 0;
120         case HUNKTYPE_DATA:
121             DEBUG("Hunk %d: DATA.\n", info->current_hunk);
122             READLW(discard, f);
123             info->hunk_offsets[info->current_hunk] = ftell(f);
124             DEBUG("Skipping data hunk. Size: %d.\n", discard * 4);
125             fseek(f, discard * 4, SEEK_CUR);
126             return 0;
127             break;
128         case HUNKTYPE_END:
129             DEBUG("END: Ending hunk %d.\n", info->current_hunk);
130             info->current_hunk++;
131             return 0;
132             break;
133         default:
134             DEBUG("Unknown hunk type %.8X! Can't process!\n", index);
135             break;
136     }
137
138     return -1;
139 }
140
141 void reloc_hunk(struct hunk_reloc *h, uint8_t *buf, struct hunk_info *i) {
142     uint32_t rel = i->hunk_offsets[h->target_hunk];
143     uint32_t *src_ptr = (uint32_t *)(&buf[i->hunk_offsets[h->src_hunk] + h->offset]);
144
145     uint32_t src = be32toh(*src_ptr);
146     uint32_t dst = src + i->base_offset + rel;
147     DEBUG("%.8X -> %.8X\n", src, dst);
148     *src_ptr = htobe32(dst);
149 }
150
151 void process_hunks(FILE *in, struct hunk_info *h_info, struct hunk_reloc *r) {
152     READLW(lw, in);
153     DEBUG("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
154
155     while(!feof(in) && process_hunk(lw, h_info, in, r) != -1) {
156         READLW(lw, in);
157         if (feof(in)) goto end_parse;
158         DEBUG("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
159         DEBUG("File pos: %.8lX\n", ftell(in));
160     }
161     end_parse:;
162     DEBUG("Done processing hunks.\n");
163 }
164
165 void reloc_hunks(struct hunk_reloc *r, uint8_t *buf, struct hunk_info *h_info) {
166     for(uint32_t i = 0; i < h_info->reloc_hunks; i++) {
167         reloc_hunk(&r[i], buf, h_info);
168         DEBUG("Relocating offset %d.\n", i);
169     }
170     DEBUG("Done relocating offsets.\n");
171 }