-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmapfile.c
165 lines (134 loc) · 4.17 KB
/
mapfile.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Code to deal with a mapfile.
// (c) 2023 Warren Toomey, GPL3.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int mapfile_loaded = 0; // Set to 1 if loaded
struct mapentry {
unsigned int addr; // Address of symbol
char *sym; // Symbol at this address
};
// Eventually, the array of mapentries sorted by address
static struct mapentry *maparray = NULL;
// Index of the most recently used mapentry
// and the count of valid mapentries
static int mapidx = 0;
static int mapcnt = 0;
// Compare mapentries by address, for qsort()
static int mapcompare(const void *a, const void *b) {
struct mapentry *c, *d;
c = (struct mapentry *) a;
d = (struct mapentry *) b;
return (c->addr - d->addr);
}
// Read the code symbols in from the mapfile
// and build the maparray.
void read_mapfile(char *filename) {
FILE *zin;
char buf[1024];
char *sym;
int i = 0;
// Free any existing map entries in case
// we get called multiple times
if (maparray != NULL) {
for (i = 0; i < mapcnt; i++)
free(maparray[i].sym);
free(maparray);
mapidx=mapcnt=0;
}
// To start with, open the file, read in
// each line and count lines with " C "
zin = fopen(filename, "r");
if (zin == NULL) { perror(filename); return; }
while (1) {
if (fgets(buf, 1023, zin) == NULL) break;
if ((strstr(buf, " C ")) != NULL) mapcnt++;
}
fclose(zin);
// Build the array of map entries.
// Add room for an extra empty element.
maparray =
(struct mapentry *) malloc((mapcnt + 1) * sizeof(struct mapentry));
if (maparray == NULL) { perror(filename); return; }
// Now re-read the file, extracting the symbol and address
zin = fopen(filename, "r");
while (1) {
if (fgets(buf, 1023, zin) == NULL) break;
if ((sym = strstr(buf, " C ")) != NULL) {
sym += 3;
// Lose \n on end of symbol
sym[strlen(sym) - 1] = '\0';
maparray[i].addr = strtol(buf, NULL, 16);
maparray[i].sym = strdup(sym);
i++;
}
}
fclose(zin);
// Sort the array by address
qsort(maparray, mapcnt, sizeof(struct mapentry), mapcompare);
// Add a final entry so we can
// index one past the end
maparray[mapcnt].addr = 0xFFFF;
maparray[mapcnt].sym = NULL;
mapfile_loaded = 1;
}
// Given a string, return the address of that symbol
// or -1 if the symbol is not found
int get_sym_address(char *sym) {
int i;
if (sym==NULL || *sym=='\0') return(-1);
for (i = 0; i < mapcnt; i++) {
if (!strcmp(maparray[i].sym, sym))
return(maparray[i].addr);
}
return(-1);
}
// Given a string, return the end address of
// the symbol, i.e. one below the next symbol
// or -1 if the symbol is not found
int get_sym_end_address(char *sym) {
int i, j;
if (sym==NULL || *sym=='\0') return(-1);
// Find the index of the symbol
for (i = 0; i < mapcnt; i++)
if (!strcmp(maparray[i].sym, sym))
break;
// Symbol not found, return error
if (i==mapcnt)
return(-1);
// Now find the next map entry
// with a higher address. We
// can go past the end with the
// extra element
for (j = i+1; j <= mapcnt; j++)
if (maparray[j].addr > maparray[i].addr)
return(maparray[j].addr - 1);
// No symbol with a higher address, error
return(-1);
}
// Given an address, return a string which
// has the nearest symbol below the address.
// Also return, through a pointer, the offset
// of the address fom the symbol.
// If NULL is returned, there is is no nearest symbol.
char *get_symbol_and_offset(unsigned int addr, int *offset) {
// No symbols
if (mapcnt == 0) return (NULL);
// Error check
if (offset == NULL) return (NULL);
// mapidx points at the last symbol used. If the address
// is at/between this symbol and the next one, use it
if ((maparray[mapidx].addr <= addr) && (maparray[mapidx+1].addr > addr)) {
*offset = addr - maparray[mapidx].addr;
return (maparray[mapidx].sym);
}
// No luck. Search the whole list to find a suitable symbol
for (mapidx = 0; mapidx < mapcnt; mapidx++) {
if ((maparray[mapidx].addr <= addr) && (maparray[mapidx+1].addr > addr)) {
*offset = addr - maparray[mapidx].addr;
return (maparray[mapidx].sym);
}
}
// No symbol found, give up
return (NULL);
}