source: vendor/emx/current/src/emxbind/map.c

Last change on this file was 18, checked in by bird, 23 years ago

Initial revision

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