source: trunk/emx/src/emxbind/map.c@ 2446

Last change on this file since 2446 was 236, checked in by zap, 22 years ago

See ChangeLog.

  • Property cvs2svn:cvs-rev set to 1.4
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 7.8 KB
Line 
1/* map.c -- Write .map file
2 Copyright (c) 1994-1996 Eberhard Mattes
3
4This file is part of emxbind.
5
6emxbind is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11emxbind is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with emxbind; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <alloca.h>
26#include "defs.h"
27#include "emxbind.h"
28
29struct map_sym
30{
31 dword addr;
32 char *name;
33 char *imp_name;
34 const char *imp_mod;
35 int imp_ord;
36 byte seg;
37};
38
39static FILE *map_file;
40static int first_dgroup_seg;
41static int text_seg;
42static int data_seg;
43static int map_sym_count = 0;
44static int map_sym_alloc = 0;
45static struct map_sym *map_sym_table = NULL;
46
47
48/* Write the header of the .map file. It includes the module name. */
49
50static void map_header (void)
51{
52 fprintf (map_file, "\n %s\n\n", module_name);
53}
54
55
56/* Write the segment list to the .map file. */
57
58static void map_segments (void)
59{
60 int seg;
61 char *fmt = " %.4X:%.8X 0%.8XH %-22s %s 32-bit\n";
62
63 fputs (" Start Length Name Class\n", map_file);
64 seg = 0;
65 text_seg = ++seg;
66 fprintf (map_file, fmt, seg, 0, a_in_h.a_text, "TEXT32", "CODE");
67 first_dgroup_seg = data_seg = ++seg;
68 fprintf (map_file, fmt, seg, 0, a_in_h.a_data, "DATA32", "DATA");
69 fprintf (map_file, fmt, seg, a_in_h.a_data, a_in_h.a_bss, "BSS32", "BSS");
70
71 if (obj_heap.virt_size != 0)
72 fprintf (map_file, fmt, ++seg, 0, obj_heap.virt_size, "HEAP", "HEAP");
73 if (obj_stk0.virt_size != 0)
74 fprintf (map_file, fmt, ++seg, 0, obj_stk0.virt_size, "STACK", "STACK");
75}
76
77
78/* Write the group list to the .map file. */
79
80static void map_groups (void)
81{
82 char *fmt = " %.4X:0 %s\n";
83
84 fputs ("\n Origin Group\n", map_file);
85 fprintf (map_file, fmt, 0, "FLAT");
86 fprintf (map_file, fmt, first_dgroup_seg, "DGROUP");
87}
88
89
90/* Compare two `struct map_sym' by name for qsort(). */
91
92static int cmp_by_name (const void *p1, const void *p2)
93{
94 return strcmp (((const struct map_sym *)p1)->name,
95 ((const struct map_sym *)p2)->name);
96}
97
98
99/* Compare two `struct map_sym' by value for qsort(). */
100
101static int cmp_by_value (const void *p1, const void *p2)
102{
103 const struct map_sym *s1, *s2;
104
105 s1 = (const struct map_sym *)p1;
106 s2 = (const struct map_sym *)p2;
107 if (s1->seg < s2->seg)
108 return -1;
109 else if (s1->seg > s2->seg)
110 return 1;
111 else if (s1->addr < s2->addr)
112 return -1;
113 else if (s1->addr > s2->addr)
114 return 1;
115 else
116 return strcmp (s1->name, s2->name);
117}
118
119
120/* Write a list of public symbols to the .map file. */
121
122static void map_publics (const char *title,
123 int (*compare)(const void *p1, const void *p2))
124{
125 int i;
126
127 fprintf (map_file, "\n Address Publics by %s\n\n", title);
128 qsort (map_sym_table, map_sym_count, sizeof (*map_sym_table), compare);
129 for (i = 0; i < map_sym_count; ++i)
130 if (map_sym_table[i].imp_mod == NULL)
131 fprintf (map_file, " %.4X:%.8lX %s\n", map_sym_table[i].seg,
132 map_sym_table[i].addr, map_sym_table[i].name);
133 else if (map_sym_table[i].imp_name != NULL)
134 fprintf (map_file, " %.4X:%.8lX Imp %-20s (%s.%s)\n", 0, 0L,
135 map_sym_table[i].name, map_sym_table[i].imp_mod,
136 map_sym_table[i].imp_name);
137 else
138 fprintf (map_file, " %.4X:%.8lX Imp %-20s (%s.%d)\n", 0, 0L,
139 map_sym_table[i].name, map_sym_table[i].imp_mod,
140 map_sym_table[i].imp_ord);
141}
142
143
144static void grow_map_sym_table (void)
145{
146 if (map_sym_count >= map_sym_alloc)
147 {
148 map_sym_alloc += 256;
149 map_sym_table = xrealloc (map_sym_table,
150 map_sym_alloc * sizeof (*map_sym_table));
151 }
152}
153
154
155/* Remember an import symbol for the .map file. Note: MAP points to a
156 module_data[].name string. */
157
158void map_import (const char *sym_name, const char *mod, const char *name,
159 int ord)
160{
161 int i;
162
163 /* TODO: Use hashing. */
164
165 for (i = 0; i < map_sym_count; ++i)
166 if (strcmp (map_sym_table[i].name, sym_name) == 0)
167 return;
168
169 grow_map_sym_table ();
170 map_sym_table[map_sym_count].name = xstrdup (sym_name);
171 if (name == NULL)
172 {
173 map_sym_table[map_sym_count].imp_name = NULL;
174 map_sym_table[map_sym_count].imp_ord = ord;
175 }
176 else
177 {
178 map_sym_table[map_sym_count].imp_name = xstrdup (name);
179 map_sym_table[map_sym_count].imp_ord = -1;
180 }
181
182 map_sym_table[map_sym_count].imp_mod = mod;
183 map_sym_table[map_sym_count].seg = 0;
184 map_sym_table[map_sym_count].addr = 0;
185 ++map_sym_count;
186}
187
188
189/* Read and prepare the symbol table, write lists of public symbols. */
190
191static void map_symbols (void)
192{
193 int i, seg;
194 dword addr;
195 char *name;
196
197 read_sym ();
198 if (sym_count != 0)
199 {
200 for (i = 0; i < sym_count; ++i)
201 {
202 switch (sym_image[i].n_type)
203 {
204 case N_TEXT|N_EXT:
205 seg = text_seg; addr = sym_image[i].n_value - obj_text.virt_base;
206 break;
207 case N_DATA|N_EXT:
208 case N_BSS|N_EXT:
209 seg = data_seg; addr = sym_image[i].n_value - obj_data.virt_base;
210 break;
211 default:
212 seg = 0; addr = 0; break;
213 }
214 if (seg != 0)
215 {
216 grow_map_sym_table ();
217 name = sym_image[i].n_un.n_strx + str_image;
218 map_sym_table[map_sym_count].seg = seg;
219 map_sym_table[map_sym_count].addr = addr;
220 map_sym_table[map_sym_count].name = name;
221 map_sym_table[map_sym_count].imp_name = NULL;
222 map_sym_table[map_sym_count].imp_mod = NULL;
223 map_sym_table[map_sym_count].imp_ord = -1;
224 ++map_sym_count;
225 }
226 }
227 if (map_sym_count != 0)
228 {
229 map_publics ("Name", cmp_by_name);
230 map_publics ("Value", cmp_by_value);
231 }
232 }
233}
234
235
236/* Write the list of exported symbols to the .map file. */
237
238static void map_exports (void)
239{
240 int i, seg;
241 const struct export *p;
242
243 if (!dll_flag || get_export (0) == NULL)
244 return;
245
246 fputs ("\n Address Export Alias\n\n", map_file);
247 for (i = 0; (p = get_export (i)) != NULL; ++i)
248 {
249 switch (p->object)
250 {
251 case OBJ_TEXT:
252 seg = text_seg; break;
253 case OBJ_DATA:
254 seg = data_seg; break;
255 default:
256 seg = 0; break;
257 }
258 if (seg != 0)
259 fprintf (map_file, " %.4X:%.8lX %-23s %s\n",
260 seg, p->offset, p->entryname, p->internalname);
261 }
262}
263
264
265/* Write the entry point to the .map file. */
266
267static void map_entrypoint (void)
268{
269 if (!dll_flag)
270 fprintf (map_file, "\nProgram entry point at 0001:00000000\n");
271}
272
273
274/* Write the .map file. */
275
276void write_map (const char *fname)
277{
278 char *tmp;
279
280 /* Add an `.map' suffix if there's no file name extension. */
281
282 tmp = alloca (strlen (fname) + 5);
283 strcpy (tmp, fname);
284 _defext (tmp, "map");
285 fname = tmp;
286
287 /* Don't use my_open() etc., those functions are for binary files. */
288
289 map_file = fopen (fname, "w");
290 if (map_file == NULL)
291 error ("cannot open `%s'", fname);
292
293 /* Write the sections of the .map file. */
294
295 map_header ();
296 map_segments ();
297 map_groups ();
298 map_exports ();
299 map_symbols ();
300 map_entrypoint ();
301
302 /* Close the .map file. */
303
304 if (fflush (map_file) != 0)
305 error ("Cannot write `%s'", fname);
306 if (fclose (map_file) != 0)
307 error ("Cannot close `%s'", fname);
308}
Note: See TracBrowser for help on using the repository browser.