source: trunk/emx/src/emxbind/export.c

Last change on this file was 3703, checked in by bird, 15 years ago

moddef.h,emxbind,weakld: Expanded the symbol name fields in libmoddef so that we can parse def-files with long symbols before truncating them (weakld). References #37.

  • Property cvs2svn:cvs-rev set to 1.5
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 6.4 KB
Line 
1/* export.c -- Export symbols
2 Copyright (c) 1991-1995 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 <sys/moddef.h>
26#include "defs.h"
27#include "emxbind.h"
28
29
30/* Export definitions from EXPORTS statements. */
31
32static struct export *export_data = NULL;
33static int export_size = 0;
34static int export_len = 0;
35
36
37/* Add an export entry to the exports table. Adding an export
38 (external name or ordinal) which already exists is a fatal error.
39 Exporting a symbol with different external names triggers a warning
40 message. */
41
42void add_export (const struct export *exp)
43{
44 int i;
45
46 for (i = 0; i < export_len; ++i)
47 {
48 if (strcmp (exp->entryname, export_data[i].entryname) == 0)
49 error ("export multiply defined: %s", exp->entryname);
50 if ((verbosity >= 2) &&
51 (strcmp (exp->internalname, export_data[i].internalname) == 0))
52 printf ("emxbind: %s multiply exported (warning)\n",
53 exp->internalname);
54 if (exp->ord != 0 && export_data[i].ord == exp->ord)
55 error ("ordinal %u multiply defined", (unsigned)exp->ord);
56 }
57
58 if ( !(exp->flags & _MDEP_NONAME)
59 && strlen (exp->entryname) > 255)
60 error ("exported name is too long (%d chars): %s",
61 strlen (exp->entryname), exp->entryname);
62
63 if (export_len >= export_size)
64 {
65 export_size += 32;
66 export_data = xrealloc (export_data,
67 export_size * sizeof (struct export));
68 }
69 export_data[export_len++] = *exp;
70}
71
72
73/* Add an entry name to the resident name table or non-resident name
74 table TABLE (resnames or nonresnames). NAME is the name of the
75 entrypoint, ORD is the ordinal number. */
76
77void entry_name (struct grow *table, const char *name, int ord)
78{
79 int name_len;
80 byte blen;
81 word ord16;
82
83 name_len = strlen (name);
84 if (name_len > 255)
85 {
86 warning("truncating export '%s' to 255 chars (ord %d)!", name, ord);
87 blen = 255;
88 }
89 else
90 blen = (byte)name_len;
91 ord16 = (word)ord;
92 put_grow (table, &blen, 1);
93 put_grow (table, name, name_len);
94 put_grow (table, &ord16, 2);
95}
96
97/* Compare two entries of an int array for qsort(). This function is
98 used for sorting the exported ordinal numbers. */
99
100static int int_compare (const void *x1, const void *x2)
101{
102 int a1, a2;
103
104 a1 = *(int *)x1;
105 a2 = *(int *)x2;
106 if (a1 < a2)
107 return -1;
108 else if (a1 > a2)
109 return 1;
110 else
111 return 0;
112}
113
114
115/* Compare two entries of the export table for qsort(). This function
116 is used for sorting the export table by ordinal number. */
117
118static int export_compare (const void *x1, const void *x2)
119{
120 int a1, a2;
121
122 a1 = ((struct export *)x1)->ord;
123 a2 = ((struct export *)x2)->ord;
124 if (a1 < a2)
125 return -1;
126 else if (a1 > a2)
127 return 1;
128 else
129 return 0;
130}
131
132
133/* Process the export definitions: build the entry table and update
134 the resident name table and the non-resident name table. */
135
136void exports (void)
137{
138 int i, j, n, ord, bundle;
139 struct export *exp;
140 struct nlist *nl;
141 int *used;
142 byte count;
143 byte flags;
144 byte type;
145 word object;
146 dword offset;
147
148 if (export_len != 0)
149 {
150 if (a_in_h.a_syms == 0 || a_in_str_size == 0)
151 error ("need symbol table for EXPORTS");
152 read_sym ();
153 }
154
155 /* Search symbol table */
156
157 for (i = 0; i < export_len; ++i)
158 {
159 nl = find_symbol (export_data[i].internalname);
160 if (nl == NULL)
161 error ("symbol %s undefined (EXPORTS)", export_data[i].internalname);
162 switch (nl->n_type & ~N_EXT)
163 {
164 case N_TEXT:
165 export_data[i].offset = nl->n_value - obj_text.virt_base;
166 export_data[i].object = OBJ_TEXT;
167 break;
168 case N_BSS:
169 case N_DATA:
170 export_data[i].offset = nl->n_value - obj_data.virt_base;
171 export_data[i].object = OBJ_DATA;
172 break;
173 default:
174 error ("cannot export symbol %s of type %d",
175 export_data[i].internalname, nl->n_type);
176 }
177 }
178
179 /* Assign unused ordinal numbers to entries with ord == 0 */
180
181 used = xmalloc (export_len * sizeof (int));
182 n = 0;
183 for (i = 0; i < export_len; ++i)
184 {
185 ord = export_data[i].ord;
186 if (ord != 0)
187 used[n++] = ord;
188 }
189 qsort (used, n, sizeof (int), int_compare);
190 ord = 1; j = 0;
191 for (i = 0; i < export_len; ++i)
192 if (export_data[i].ord == 0)
193 {
194 while (j < n && used[j] == ord)
195 {
196 ++ord; ++j;
197 }
198 export_data[i].ord = ord++;
199 }
200 qsort (export_data, export_len, sizeof (struct export), export_compare);
201 ord = 1; bundle = 0;
202 for (i = 0; i < export_len; ++i)
203 {
204 exp = &export_data[i];
205 if (!(exp->flags & _MDEP_NONAME))
206 entry_name ((exp->resident ? &resnames : &nonresnames),
207 exp->entryname, exp->ord);
208 if (bundle == 0)
209 {
210 while (ord < exp->ord)
211 {
212 if (exp->ord - ord > 255)
213 count = 255;
214 else
215 count = exp->ord - ord;
216 type = 0; /* empty bundle */
217 put_grow (&entry_tab, &count, 1);
218 put_grow (&entry_tab, &type, 1);
219 ord += count;
220 }
221 object = (word)exp->object;
222 bundle = 1;
223 while (i+bundle < export_len && bundle < 255 &&
224 export_data[i+bundle].ord == ord + bundle &&
225 export_data[i+bundle].object == object)
226 ++bundle;
227 count = (byte)bundle;
228 type = 3; /* entry point, 32-bit offset */
229 ++object;
230 put_grow (&entry_tab, &count, 1);
231 put_grow (&entry_tab, &type, 1);
232 put_grow (&entry_tab, &object, 2);
233 }
234 flags = 3;
235 offset = exp->offset;
236 put_grow (&entry_tab, &flags, 1);
237 put_grow (&entry_tab, &offset, 4);
238 ++ord; --bundle;
239 }
240 count = 0;
241 put_grow (&entry_tab, &count, 1);
242 if (nonresnames.len != 0)
243 put_grow (&nonresnames, &count, 1);
244}
245
246
247/* Retrieve an export entry for writing the .map file. */
248
249const struct export *get_export (int i)
250{
251 if (i < export_len)
252 return &export_data[i];
253 else
254 return NULL;
255}
Note: See TracBrowser for help on using the repository browser.