1 | /* ld.c -- changed for emx by Eberhard Mattes -- Sep 1998
|
---|
2 | changed for Innotek GCC by Andrew Zabolotny -- 2003
|
---|
3 | changed for Innotek GCC by knut st. osmundsen -- 2004
|
---|
4 | changed for RSX by Rainer Schnitker -- Feb 1996 */
|
---|
5 |
|
---|
6 | /* Linker `ld' for GNU
|
---|
7 | Copyright (C) 1988 Free Software Foundation, Inc.
|
---|
8 |
|
---|
9 | This program is free software; you can redistribute it and/or modify
|
---|
10 | it under the terms of the GNU General Public License as published by
|
---|
11 | the Free Software Foundation; either version 1, or (at your option)
|
---|
12 | any later version.
|
---|
13 |
|
---|
14 | This program is distributed in the hope that it will be useful,
|
---|
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
17 | GNU General Public License for more details.
|
---|
18 |
|
---|
19 | You should have received a copy of the GNU General Public License
|
---|
20 | along with this program; if not, write to the Free Software
|
---|
21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
---|
22 |
|
---|
23 | /* Written by Richard Stallman with some help from Eric Albert.
|
---|
24 | Set, indirect, and warning symbol features added by Randy Smith. */
|
---|
25 |
|
---|
26 | #include <ar.h>
|
---|
27 | #include <stdio.h>
|
---|
28 | #include <stdlib.h>
|
---|
29 | #include <stdarg.h>
|
---|
30 | #include <io.h>
|
---|
31 | #include <process.h>
|
---|
32 | #include <errno.h>
|
---|
33 | #include <utime.h>
|
---|
34 | #include <ctype.h>
|
---|
35 | #include <sys/types.h>
|
---|
36 | #include <sys/stat.h>
|
---|
37 | #include <sys/file.h>
|
---|
38 | #ifndef USG
|
---|
39 | #include <sys/time.h>
|
---|
40 | #include <sys/resource.h>
|
---|
41 | #endif
|
---|
42 | #ifdef __EMX__
|
---|
43 | #include <string.h>
|
---|
44 | #endif
|
---|
45 | #include "libiberty.h"
|
---|
46 |
|
---|
47 | #if !defined(A_OUT)
|
---|
48 | #define A_OUT
|
---|
49 | #endif
|
---|
50 |
|
---|
51 | #ifdef A_OUT
|
---|
52 | #include <a_out.h>
|
---|
53 | #endif
|
---|
54 |
|
---|
55 | #ifndef _System
|
---|
56 | #define _System
|
---|
57 | #endif
|
---|
58 | extern int _System DosCopy (char *, char *, int);
|
---|
59 |
|
---|
60 | /* We need .data of every module aligned to at least 16 bound
|
---|
61 | in order to support the alignments required by SSE.
|
---|
62 | Ditto for constants in .text. */
|
---|
63 | #define SECTION_ALIGN 16
|
---|
64 | #define SECTION_ALIGN_MASK (SECTION_ALIGN-1)
|
---|
65 |
|
---|
66 | /* If compiled with GNU C, use the built-in alloca */
|
---|
67 | #ifdef USE_ALLOCA
|
---|
68 | #include "alloca.h"
|
---|
69 | #define ALLOCA(size) alloca (size)
|
---|
70 | #define FREEA(ptr) do { (ptr) = NULL; } while (0)
|
---|
71 | #else
|
---|
72 | #define ALLOCA(size) malloc (size)
|
---|
73 | #define FREEA(ptr) do { free(ptr); (ptr) = NULL; } while (0)
|
---|
74 | #endif
|
---|
75 | #include "getopt.h"
|
---|
76 |
|
---|
77 | /* Always use the GNU version of debugging symbol type codes, if possible. */
|
---|
78 |
|
---|
79 | #include "stab.h"
|
---|
80 | #define CORE_ADDR unsigned long /* For symseg.h */
|
---|
81 | #include "symseg.h"
|
---|
82 |
|
---|
83 | #include <strings.h>
|
---|
84 |
|
---|
85 | /* Determine whether we should attempt to handle (minimally)
|
---|
86 | N_BINCL and N_EINCL. */
|
---|
87 |
|
---|
88 | #if defined (__GNU_STAB__) || defined (N_BINCL)
|
---|
89 | #define HAVE_SUN_STABS
|
---|
90 | #endif
|
---|
91 |
|
---|
92 | #define min(a,b) ((a) < (b) ? (a) : (b))
|
---|
93 |
|
---|
94 | /* Macro to control the number of undefined references printed */
|
---|
95 | #define MAX_UREFS_PRINTED 10
|
---|
96 |
|
---|
97 | /* Size of a page; obtained from the operating system. */
|
---|
98 |
|
---|
99 | int page_size;
|
---|
100 |
|
---|
101 | /* Name this program was invoked by. */
|
---|
102 |
|
---|
103 | char *progname;
|
---|
104 | |
---|
105 |
|
---|
106 | /* System dependencies */
|
---|
107 |
|
---|
108 | /* Define this if names etext, edata and end should not start with `_'. */
|
---|
109 | /* #define nounderscore 1 */
|
---|
110 |
|
---|
111 | /* Define NON_NATIVE if using BSD or pseudo-BSD file format on a system
|
---|
112 | whose native format is different. */
|
---|
113 | /* #define NON_NATIVE */
|
---|
114 |
|
---|
115 | /* The "address" of the data segment in a relocatable file.
|
---|
116 | The text address of a relocatable file is always
|
---|
117 | considered to be zero (instead of the value of N_TXTADDR, which
|
---|
118 | is what the address is in an executable), so we need to subtract
|
---|
119 | N_TXTADDR from N_DATADDR to get the "address" for the input file. */
|
---|
120 | #define DATA_ADDR_DOT_O(hdr) (N_DATADDR(hdr) - N_TXTADDR(hdr))
|
---|
121 |
|
---|
122 | /* Values for 3rd argument to lseek(). */
|
---|
123 | #ifndef L_SET
|
---|
124 | #define L_SET 0
|
---|
125 | #endif
|
---|
126 | /* This is called L_INCR in BSD, but SEEK_CUR in POSIX. */
|
---|
127 | #ifndef SEEK_CUR
|
---|
128 | #define SEEK_CUR 1
|
---|
129 | #endif
|
---|
130 |
|
---|
131 | /*
|
---|
132 | * Ok. Following are the relocation information macros. If your
|
---|
133 | * system cannot use the default set (below), you must define all of these:
|
---|
134 |
|
---|
135 | * relocation_info: This must be typedef'd (or #define'd) to the type
|
---|
136 | * of structure that is stored in the relocation info section of your
|
---|
137 | * a.out files. Often this is defined in the a.out.h for your system.
|
---|
138 | *
|
---|
139 | * RELOC_ADDRESS (rval): Offset into the current section of the
|
---|
140 | * <whatever> to be relocated. *Must be an lvalue*.
|
---|
141 | *
|
---|
142 | * RELOC_EXTERN_P (rval): Is this relocation entry based on an
|
---|
143 | * external symbol (1), or was it fully resolved upon entering the
|
---|
144 | * loader (0) in which case some combination of the value in memory
|
---|
145 | * (if RELOC_MEMORY_ADD_P) and the extra (if RELOC_ADD_EXTRA) contains
|
---|
146 | * what the value of the relocation actually was. *Must be an lvalue*.
|
---|
147 | *
|
---|
148 | * RELOC_TYPE (rval): For a non-external relocation, this is the
|
---|
149 | * segment to relocate for. *Must be an lvalue.*
|
---|
150 | *
|
---|
151 | * RELOC_SYMBOL (rval): For an external relocation, this is the
|
---|
152 | * index of its symbol in the symbol table. *Must be an lvalue*.
|
---|
153 | *
|
---|
154 | * RELOC_MEMORY_ADD_P (rval): This should be 1 if the final
|
---|
155 | * relocation value output here should be added to memory; 0, if the
|
---|
156 | * section of memory described should simply be set to the relocation
|
---|
157 | * value.
|
---|
158 | *
|
---|
159 | * RELOC_MEMORY_ADD_P (rval): If this is nonzero, the value previously
|
---|
160 | * present in the memory location to be relocated is *added*
|
---|
161 | * to the relocation value, to produce the final result.
|
---|
162 | * Otherwise, the relocation value is stored in the memory location
|
---|
163 | * and the value previously found there is ignored.
|
---|
164 | * By default, this is always 1.
|
---|
165 | *
|
---|
166 | * RELOC_MEMORY_SUB_P (rval): If this is nonzero, the value previously
|
---|
167 | * present in the memory location to be relocated is *subtracted*
|
---|
168 | * from the relocation value, to produce the final result.
|
---|
169 | * By default, this is always 0.
|
---|
170 | *
|
---|
171 | * RELOC_ADD_EXTRA (rval): (Optional) This macro, if defined, gives
|
---|
172 | * an extra value to be added to the relocation value based on the
|
---|
173 | * individual relocation entry. *Must be an lvalue if defined*.
|
---|
174 | *
|
---|
175 | * RELOC_PCREL_P (rval): True if the relocation value described is
|
---|
176 | * pc relative.
|
---|
177 | *
|
---|
178 | * RELOC_VALUE_RIGHTSHIFT (rval): Number of bits right to shift the
|
---|
179 | * final relocation value before putting it where it belongs.
|
---|
180 | *
|
---|
181 | * RELOC_TARGET_SIZE (rval): log to the base 2 of the number of
|
---|
182 | * bytes of size this relocation entry describes; 1 byte == 0; 2 bytes
|
---|
183 | * == 1; 4 bytes == 2, and etc. This is somewhat redundant (we could
|
---|
184 | * do everything in terms of the bit operators below), but having this
|
---|
185 | * macro could end up producing better code on machines without fancy
|
---|
186 | * bit twiddling. Also, it's easier to understand/code big/little
|
---|
187 | * endian distinctions with this macro.
|
---|
188 | *
|
---|
189 | * RELOC_TARGET_BITPOS (rval): The starting bit position within the
|
---|
190 | * object described in RELOC_TARGET_SIZE in which the relocation value
|
---|
191 | * will go.
|
---|
192 | *
|
---|
193 | * RELOC_TARGET_BITSIZE (rval): How many bits are to be replaced
|
---|
194 | * with the bits of the relocation value. It may be assumed by the
|
---|
195 | * code that the relocation value will fit into this many bits. This
|
---|
196 | * may be larger than RELOC_TARGET_SIZE if such be useful.
|
---|
197 | *
|
---|
198 | *
|
---|
199 | * Things I haven't implemented
|
---|
200 | * ----------------------------
|
---|
201 | *
|
---|
202 | * Values for RELOC_TARGET_SIZE other than 0, 1, or 2.
|
---|
203 | *
|
---|
204 | * Pc relative relocation for External references.
|
---|
205 | *
|
---|
206 | *
|
---|
207 | */
|
---|
208 |
|
---|
209 | /* Default macros */
|
---|
210 | #ifndef RELOC_ADDRESS
|
---|
211 | #define RELOC_ADDRESS(r) ((r)->r_address)
|
---|
212 | #define RELOC_EXTERN_P(r) ((r)->r_extern)
|
---|
213 | #define RELOC_TYPE(r) ((r)->r_symbolnum)
|
---|
214 | #define RELOC_SYMBOL(r) ((r)->r_symbolnum)
|
---|
215 | #define RELOC_MEMORY_SUB_P(r) 0
|
---|
216 | #define RELOC_MEMORY_ADD_P(r) 1
|
---|
217 | #undef RELOC_ADD_EXTRA
|
---|
218 | #define RELOC_PCREL_P(r) ((r)->r_pcrel)
|
---|
219 | #define RELOC_VALUE_RIGHTSHIFT(r) 0
|
---|
220 | #define RELOC_TARGET_SIZE(r) ((r)->r_length)
|
---|
221 | #define RELOC_TARGET_BITPOS(r) 0
|
---|
222 | #define RELOC_TARGET_BITSIZE(r) 32
|
---|
223 | #endif
|
---|
224 |
|
---|
225 | #ifndef MAX_ALIGNMENT
|
---|
226 | #define MAX_ALIGNMENT (sizeof (int))
|
---|
227 | #endif
|
---|
228 |
|
---|
229 | #ifdef nounderscore
|
---|
230 | #define LPREFIX '.'
|
---|
231 | #else
|
---|
232 | #define LPREFIX 'L'
|
---|
233 | #endif
|
---|
234 |
|
---|
235 | |
---|
236 |
|
---|
237 | /* Special global symbol types understood by GNU LD. */
|
---|
238 |
|
---|
239 | /* The following type indicates the definition of a symbol as being
|
---|
240 | an indirect reference to another symbol. The other symbol
|
---|
241 | appears as an undefined reference, immediately following this symbol.
|
---|
242 |
|
---|
243 | Indirection is asymmetrical. The other symbol's value will be used
|
---|
244 | to satisfy requests for the indirect symbol, but not vice versa.
|
---|
245 | If the other symbol does not have a definition, libraries will
|
---|
246 | be searched to find a definition.
|
---|
247 |
|
---|
248 | So, for example, the following two lines placed in an assembler
|
---|
249 | input file would result in an object file which would direct gnu ld
|
---|
250 | to resolve all references to symbol "foo" as references to symbol
|
---|
251 | "bar".
|
---|
252 |
|
---|
253 | .stabs "_foo",11,0,0,0
|
---|
254 | .stabs "_bar",1,0,0,0
|
---|
255 |
|
---|
256 | Note that (11 == (N_INDR | N_EXT)) and (1 == (N_UNDF | N_EXT)). */
|
---|
257 |
|
---|
258 | #ifndef N_INDR
|
---|
259 | #define N_INDR 0xa
|
---|
260 | #endif
|
---|
261 |
|
---|
262 | /* The following symbols refer to set elements. These are expected
|
---|
263 | only in input to the loader; they should not appear in loader
|
---|
264 | output (unless relocatable output is requested). To be recognized
|
---|
265 | by the loader, the input symbols must have their N_EXT bit set.
|
---|
266 | All the N_SET[ATDB] symbols with the same name form one set. The
|
---|
267 | loader collects all of these elements at load time and outputs a
|
---|
268 | vector for each name.
|
---|
269 | Space (an array of 32 bit words) is allocated for the set in the
|
---|
270 | data section, and the n_value field of each set element value is
|
---|
271 | stored into one word of the array.
|
---|
272 | The first word of the array is the length of the set (number of
|
---|
273 | elements). The last word of the vector is set to zero for possible
|
---|
274 | use by incremental loaders. The array is ordered by the linkage
|
---|
275 | order; the first symbols which the linker encounters will be first
|
---|
276 | in the array.
|
---|
277 |
|
---|
278 | In C syntax this looks like:
|
---|
279 |
|
---|
280 | struct set_vector {
|
---|
281 | unsigned int length;
|
---|
282 | unsigned int vector[length];
|
---|
283 | unsigned int always_zero;
|
---|
284 | };
|
---|
285 |
|
---|
286 | Before being placed into the array, each element is relocated
|
---|
287 | according to its type. This allows the loader to create an array
|
---|
288 | of pointers to objects automatically. N_SETA type symbols will not
|
---|
289 | be relocated.
|
---|
290 |
|
---|
291 | The address of the set is made into an N_SETV symbol
|
---|
292 | whose name is the same as the name of the set.
|
---|
293 | This symbol acts like a N_DATA global symbol
|
---|
294 | in that it can satisfy undefined external references.
|
---|
295 |
|
---|
296 | For the purposes of determining whether or not to load in a library
|
---|
297 | file, set element definitions are not considered "real
|
---|
298 | definitions"; they will not cause the loading of a library
|
---|
299 | member.
|
---|
300 |
|
---|
301 | If relocatable output is requested, none of this processing is
|
---|
302 | done. The symbols are simply relocated and passed through to the
|
---|
303 | output file.
|
---|
304 |
|
---|
305 | So, for example, the following three lines of assembler code
|
---|
306 | (whether in one file or scattered between several different ones)
|
---|
307 | will produce a three element vector (total length is five words;
|
---|
308 | see above), referenced by the symbol "_xyzzy", which will have the
|
---|
309 | addresses of the routines _init1, _init2, and _init3.
|
---|
310 |
|
---|
311 | *NOTE*: If symbolic addresses are used in the n_value field of the
|
---|
312 | defining .stabs, those symbols must be defined in the same file as
|
---|
313 | that containing the .stabs.
|
---|
314 |
|
---|
315 | .stabs "_xyzzy",23,0,0,_init1
|
---|
316 | .stabs "_xyzzy",23,0,0,_init2
|
---|
317 | .stabs "_xyzzy",23,0,0,_init3
|
---|
318 |
|
---|
319 | Note that (23 == (N_SETT | N_EXT)). */
|
---|
320 |
|
---|
321 | #ifndef N_SETA
|
---|
322 | #define N_SETA 0x14 /* Absolute set element symbol */
|
---|
323 | #endif /* This is input to LD, in a .o file. */
|
---|
324 |
|
---|
325 | #ifndef N_SETT
|
---|
326 | #define N_SETT 0x16 /* Text set element symbol */
|
---|
327 | #endif /* This is input to LD, in a .o file. */
|
---|
328 |
|
---|
329 | #ifndef N_SETD
|
---|
330 | #define N_SETD 0x18 /* Data set element symbol */
|
---|
331 | #endif /* This is input to LD, in a .o file. */
|
---|
332 |
|
---|
333 | #ifndef N_SETB
|
---|
334 | #define N_SETB 0x1A /* Bss set element symbol */
|
---|
335 | #endif /* This is input to LD, in a .o file. */
|
---|
336 |
|
---|
337 | /* Macros dealing with the set element symbols defined in a.out.h */
|
---|
338 | #define SET_ELEMENT_P(x) ((x)>=N_SETA&&(x)<=(N_SETB|N_EXT))
|
---|
339 | #define TYPE_OF_SET_ELEMENT(x) ((x)-N_SETA+N_ABS)
|
---|
340 |
|
---|
341 | #ifndef N_SETV
|
---|
342 | #define N_SETV 0x1C /* Pointer to set vector in data area. */
|
---|
343 | #endif /* This is output from LD. */
|
---|
344 |
|
---|
345 | /* Check if a symbol is weak */
|
---|
346 | #define WEAK_SYMBOL(t) (((t) >= N_WEAKU) && ((t) <= N_WEAKB))
|
---|
347 |
|
---|
348 | /* If a this type of symbol is encountered, its name is a warning
|
---|
349 | message to print each time the symbol referenced by the next symbol
|
---|
350 | table entry is referenced.
|
---|
351 |
|
---|
352 | This feature may be used to allow backwards compatibility with
|
---|
353 | certain functions (eg. gets) but to discourage programmers from
|
---|
354 | their use.
|
---|
355 |
|
---|
356 | So if, for example, you wanted to have ld print a warning whenever
|
---|
357 | the function "gets" was used in their C program, you would add the
|
---|
358 | following to the assembler file in which gets is defined:
|
---|
359 |
|
---|
360 | .stabs "Obsolete function \"gets\" referenced",30,0,0,0
|
---|
361 | .stabs "_gets",1,0,0,0
|
---|
362 |
|
---|
363 | These .stabs do not necessarily have to be in the same file as the
|
---|
364 | gets function, they simply must exist somewhere in the compilation. */
|
---|
365 |
|
---|
366 | #ifndef N_WARNING
|
---|
367 | #define N_WARNING 0x1E /* Warning message to print if symbol
|
---|
368 | included */
|
---|
369 | #endif /* This is input to ld */
|
---|
370 |
|
---|
371 | #ifndef __GNU_STAB__
|
---|
372 |
|
---|
373 | /* Line number for the data section. This is to be used to describe
|
---|
374 | the source location of a variable declaration. */
|
---|
375 | #ifndef N_DSLINE
|
---|
376 | #define N_DSLINE (N_SLINE+N_DATA-N_TEXT)
|
---|
377 | #endif
|
---|
378 |
|
---|
379 | /* Line number for the bss section. This is to be used to describe
|
---|
380 | the source location of a variable declaration. */
|
---|
381 | #ifndef N_BSLINE
|
---|
382 | #define N_BSLINE (N_SLINE+N_BSS-N_TEXT)
|
---|
383 | #endif
|
---|
384 |
|
---|
385 | #endif /* not __GNU_STAB__ */
|
---|
386 | |
---|
387 |
|
---|
388 | /* Symbol table */
|
---|
389 |
|
---|
390 | /* Global symbol data is recorded in these structures,
|
---|
391 | one for each global symbol.
|
---|
392 | They are found via hashing in 'symtab', which points to a vector of buckets.
|
---|
393 | Each bucket is a chain of these structures through the link field. */
|
---|
394 |
|
---|
395 | typedef
|
---|
396 | struct glosym
|
---|
397 | {
|
---|
398 | /* Pointer to next symbol in this symbol's hash bucket. */
|
---|
399 | struct glosym *link;
|
---|
400 | /* Name of this symbol. */
|
---|
401 | char *name;
|
---|
402 | /* Value of this symbol as a global symbol. */
|
---|
403 | long value;
|
---|
404 | /* Chain of external 'nlist's in files for this symbol, both defs
|
---|
405 | and refs. */
|
---|
406 | struct nlist *refs;
|
---|
407 | /* Any warning message that might be associated with this symbol
|
---|
408 | from an N_WARNING symbol encountered. */
|
---|
409 | char *warning;
|
---|
410 | /* Nonzero means definitions of this symbol as common have been seen,
|
---|
411 | and the value here is the largest size specified by any of them. */
|
---|
412 | int max_common_size;
|
---|
413 | /* For OUTPUT_RELOCATABLE, records the index of this global sym in the
|
---|
414 | symbol table to be written, with the first global sym given index 0.*/
|
---|
415 | int def_count;
|
---|
416 | /* Nonzero means a definition of this global symbol is known to exist.
|
---|
417 | Library members should not be loaded on its account. */
|
---|
418 | char defined;
|
---|
419 | /* Nonzero means a reference to this global symbol has been seen
|
---|
420 | in a file that is surely being loaded.
|
---|
421 | A value higher than 1 is the n_type code for the symbol's
|
---|
422 | definition. */
|
---|
423 | char referenced;
|
---|
424 | /* A count of the number of undefined references printed for a
|
---|
425 | specific symbol. If a symbol is unresolved at the end of
|
---|
426 | digest_symbols (and the loading run is supposed to produce
|
---|
427 | relocatable output) do_file_warnings keeps track of how many
|
---|
428 | unresolved reference error messages have been printed for
|
---|
429 | each symbol here. When the number hits MAX_UREFS_PRINTED,
|
---|
430 | messages stop. */
|
---|
431 | unsigned char undef_refs;
|
---|
432 | /* 1 means that this symbol has multiple definitions. 2 means
|
---|
433 | that it has multiple definitions, and some of them are set
|
---|
434 | elements, one of which has been printed out already. */
|
---|
435 | unsigned char multiply_defined;
|
---|
436 | /* Nonzero means print a message at all refs or defs of this symbol */
|
---|
437 | char trace;
|
---|
438 | /* One of N_WEAKX values */
|
---|
439 | char weak;
|
---|
440 | }
|
---|
441 | symbol;
|
---|
442 |
|
---|
443 | /* Demangler for C++. */
|
---|
444 | #include "demangle.h"
|
---|
445 | static char *my_cplus_demangle (const char *);
|
---|
446 | int demangle_options;
|
---|
447 |
|
---|
448 | /* Demangler function to use. We unconditionally enable the C++ demangler
|
---|
449 | because we assume any name it successfully demangles was probably produced
|
---|
450 | by the C++ compiler. Enabling it only if -lg++ was specified seems too
|
---|
451 | much of a kludge. */
|
---|
452 | char *(*demangler)() = my_cplus_demangle;
|
---|
453 |
|
---|
454 | /* Number of buckets in symbol hash table */
|
---|
455 | #define TABSIZE 1009
|
---|
456 |
|
---|
457 | /* The symbol hash table: a vector of TABSIZE pointers to struct glosym. */
|
---|
458 | symbol *symtab[TABSIZE];
|
---|
459 |
|
---|
460 | /* Number of symbols in symbol hash table. */
|
---|
461 | int num_hash_tab_syms = 0;
|
---|
462 |
|
---|
463 | /* Count the number of nlist entries that are for local symbols.
|
---|
464 | This count and the three following counts
|
---|
465 | are incremented as as symbols are entered in the symbol table. */
|
---|
466 | int local_sym_count;
|
---|
467 |
|
---|
468 | /* Count number of nlist entries that are for local symbols
|
---|
469 | whose names don't start with L. */
|
---|
470 | int non_L_local_sym_count;
|
---|
471 |
|
---|
472 | /* Count the number of nlist entries for debugger info. */
|
---|
473 | int debugger_sym_count;
|
---|
474 |
|
---|
475 | /* Count the number of global symbols referenced and not defined. */
|
---|
476 | int undefined_global_sym_count;
|
---|
477 |
|
---|
478 | /* Count the number of global symbols multiply defined. */
|
---|
479 | int multiple_def_count;
|
---|
480 |
|
---|
481 | /* Count the number of defined global symbols.
|
---|
482 | Each symbol is counted only once
|
---|
483 | regardless of how many different nlist entries refer to it,
|
---|
484 | since the output file will need only one nlist entry for it.
|
---|
485 | This count is computed by `digest_symbols';
|
---|
486 | it is undefined while symbols are being loaded. */
|
---|
487 | int defined_global_sym_count;
|
---|
488 |
|
---|
489 | /* Count the number of symbols defined through common declarations.
|
---|
490 | This count is kept in symdef_library, linear_library, and
|
---|
491 | enter_global_ref. It is incremented when the defined flag is set
|
---|
492 | in a symbol because of a common definition, and decremented when
|
---|
493 | the symbol is defined "for real" (ie. by something besides a common
|
---|
494 | definition). */
|
---|
495 | int common_defined_global_count;
|
---|
496 |
|
---|
497 | /* Count the number of set element type symbols and the number of
|
---|
498 | separate vectors which these symbols will fit into. See the
|
---|
499 | GNU a.out.h for more info.
|
---|
500 | This count is computed by 'enter_file_symbols' */
|
---|
501 | int set_symbol_count;
|
---|
502 | int set_vector_count;
|
---|
503 |
|
---|
504 | /* Define a linked list of strings which define symbols which should
|
---|
505 | be treated as set elements even though they aren't. Any symbol
|
---|
506 | with a prefix matching one of these should be treated as a set
|
---|
507 | element.
|
---|
508 |
|
---|
509 | This is to make up for deficiencies in many assemblers which aren't
|
---|
510 | willing to pass any stabs through to the loader which they don't
|
---|
511 | understand. */
|
---|
512 | struct string_list_element {
|
---|
513 | char *str;
|
---|
514 | struct string_list_element *next;
|
---|
515 | };
|
---|
516 |
|
---|
517 | struct string_list_element *set_element_prefixes;
|
---|
518 |
|
---|
519 | /* Count the number of definitions done indirectly (ie. done relative
|
---|
520 | to the value of some other symbol. */
|
---|
521 | int global_indirect_count;
|
---|
522 |
|
---|
523 | /* Count the number of warning symbols encountered. */
|
---|
524 | int warning_count;
|
---|
525 |
|
---|
526 | /* Total number of symbols to be written in the output file.
|
---|
527 | Computed by digest_symbols from the variables above. */
|
---|
528 | int nsyms;
|
---|
529 |
|
---|
530 |
|
---|
531 | /* Nonzero means ptr to symbol entry for symbol to use as start addr.
|
---|
532 | -e sets this. */
|
---|
533 | symbol *entry_symbol;
|
---|
534 |
|
---|
535 | /* These can be NULL if we don't actually have such a symbol. */
|
---|
536 | symbol *edata_symbol; /* the symbol _edata */
|
---|
537 | symbol *etext_symbol; /* the symbol _etext */
|
---|
538 | symbol *end_symbol; /* the symbol _end */
|
---|
539 | /* We also need __{edata,etext,end} so that they can safely
|
---|
540 | be used from an ANSI library. */
|
---|
541 | symbol *edata_symbol_alt;
|
---|
542 | symbol *etext_symbol_alt;
|
---|
543 | symbol *end_symbol_alt;
|
---|
544 | |
---|
545 |
|
---|
546 | /* Kinds of files potentially understood by the linker. */
|
---|
547 |
|
---|
548 | enum file_type { IS_UNKNOWN, IS_ARCHIVE, IS_A_OUT, IS_MACH_O };
|
---|
549 |
|
---|
550 | /* Each input file, and each library member ("subfile") being loaded,
|
---|
551 | has a `file_entry' structure for it.
|
---|
552 |
|
---|
553 | For files specified by command args, these are contained in the vector
|
---|
554 | which `file_table' points to.
|
---|
555 |
|
---|
556 | For library members, they are dynamically allocated,
|
---|
557 | and chained through the `chain' field.
|
---|
558 | The chain is found in the `subfiles' field of the `file_entry'.
|
---|
559 | The `file_entry' objects for the members have `superfile' fields pointing
|
---|
560 | to the one for the library. */
|
---|
561 |
|
---|
562 | struct file_entry {
|
---|
563 | /* Name of this file. */
|
---|
564 | char *filename;
|
---|
565 |
|
---|
566 | /* What kind of file this is. */
|
---|
567 | enum file_type file_type;
|
---|
568 |
|
---|
569 | /* Name to use for the symbol giving address of text start */
|
---|
570 | /* Usually the same as filename, but for a file spec'd with -l
|
---|
571 | this is the -l switch itself rather than the filename. */
|
---|
572 | char *local_sym_name;
|
---|
573 |
|
---|
574 | /* Describe the layout of the contents of the file. */
|
---|
575 |
|
---|
576 | /* The text section. */
|
---|
577 | unsigned long int orig_text_address;
|
---|
578 | unsigned long int text_size;
|
---|
579 | long int text_offset;
|
---|
580 |
|
---|
581 | /* Text relocation. */
|
---|
582 | unsigned long int text_reloc_size;
|
---|
583 | long int text_reloc_offset;
|
---|
584 |
|
---|
585 | /* The data section. */
|
---|
586 | unsigned long int orig_data_address;
|
---|
587 | unsigned long int data_size;
|
---|
588 | long int data_offset;
|
---|
589 |
|
---|
590 | /* Data relocation. */
|
---|
591 | unsigned long int data_reloc_size;
|
---|
592 | long int data_reloc_offset;
|
---|
593 |
|
---|
594 | /* The bss section. */
|
---|
595 | unsigned long int orig_bss_address;
|
---|
596 | unsigned long int bss_size;
|
---|
597 |
|
---|
598 | /* The symbol and string tables. */
|
---|
599 | unsigned long int syms_size;
|
---|
600 | long int syms_offset;
|
---|
601 | unsigned long int strs_size;
|
---|
602 | long int strs_offset;
|
---|
603 |
|
---|
604 | /* The GDB symbol segment, if any. */
|
---|
605 | unsigned long int symseg_size;
|
---|
606 | long int symseg_offset;
|
---|
607 |
|
---|
608 | /* Describe data from the file loaded into core */
|
---|
609 |
|
---|
610 | /* Symbol table of the file. */
|
---|
611 | struct nlist *symbols;
|
---|
612 |
|
---|
613 | /* Pointer to the string table.
|
---|
614 | The string table is not kept in core all the time,
|
---|
615 | but when it is in core, its address is here. */
|
---|
616 | char *strings;
|
---|
617 |
|
---|
618 | /* Next two used only if OUTPUT_RELOCATABLE or if needed for */
|
---|
619 | /* output of undefined reference line numbers. */
|
---|
620 |
|
---|
621 | /* Text reloc info saved by `write_text' for `coptxtrel'. */
|
---|
622 | struct relocation_info *textrel;
|
---|
623 | /* Data reloc info saved by `write_data' for `copdatrel'. */
|
---|
624 | struct relocation_info *datarel;
|
---|
625 |
|
---|
626 | /* Relation of this file's segments to the output file */
|
---|
627 |
|
---|
628 | /* Start of this file's text seg in the output file core image. */
|
---|
629 | int text_start_address;
|
---|
630 | /* Start of this file's data seg in the output file core image. */
|
---|
631 | int data_start_address;
|
---|
632 | /* Start of this file's bss seg in the output file core image. */
|
---|
633 | int bss_start_address;
|
---|
634 | /* Offset in bytes in the output file symbol table
|
---|
635 | of the first local symbol for this file. Set by `write_file_symbols'. */
|
---|
636 | int local_syms_offset;
|
---|
637 |
|
---|
638 | /* For library members only */
|
---|
639 |
|
---|
640 | /* For a library, points to chain of entries for the library members. */
|
---|
641 | struct file_entry *subfiles;
|
---|
642 | /* For a library member, offset of the member within the archive.
|
---|
643 | Zero for files that are not library members. */
|
---|
644 | int starting_offset;
|
---|
645 | /* Size of contents of this file, if library member. */
|
---|
646 | int total_size;
|
---|
647 | /* For library member, points to the library's own entry. */
|
---|
648 | struct file_entry *superfile;
|
---|
649 | /* For library member, points to next entry for next member. */
|
---|
650 | struct file_entry *chain;
|
---|
651 |
|
---|
652 | /* 1 if file is a library. */
|
---|
653 | char library_flag;
|
---|
654 |
|
---|
655 | /* 1 if file's header has been read into this structure. */
|
---|
656 | char header_read_flag;
|
---|
657 |
|
---|
658 | /* 1 means search a set of directories for this file. */
|
---|
659 | char search_dirs_flag;
|
---|
660 |
|
---|
661 | /* 1 means this is base file of incremental load.
|
---|
662 | Do not load this file's text or data.
|
---|
663 | Also default text_start to after this file's bss. */
|
---|
664 | char just_syms_flag;
|
---|
665 |
|
---|
666 | /* 1 means search for dynamic libs before static.
|
---|
667 | 0 means search only static libs. */
|
---|
668 | char dynamic;
|
---|
669 | };
|
---|
670 |
|
---|
671 | /* Vector of entries for input files specified by arguments.
|
---|
672 | These are all the input files except for members of specified libraries. */
|
---|
673 | struct file_entry *file_table;
|
---|
674 |
|
---|
675 | /* Length of that vector. */
|
---|
676 | int number_of_files;
|
---|
677 | |
---|
678 |
|
---|
679 | /* When loading the text and data, we can avoid doing a close
|
---|
680 | and another open between members of the same library.
|
---|
681 |
|
---|
682 | These two variables remember the file that is currently open.
|
---|
683 | Both are zero if no file is open.
|
---|
684 |
|
---|
685 | See `each_file' and `file_close'. */
|
---|
686 |
|
---|
687 | struct file_entry *input_file;
|
---|
688 | int input_desc;
|
---|
689 |
|
---|
690 | /* The name of the file to write; "a.out" by default. */
|
---|
691 |
|
---|
692 | char *output_filename;
|
---|
693 | char *exe_filename;
|
---|
694 | char *def_filename = NULL;
|
---|
695 | char *res_filename = NULL;
|
---|
696 | char *map_filename = NULL;
|
---|
697 | char *touch_filename = NULL;
|
---|
698 | int reloc_flag = 0;
|
---|
699 | int dll_flag = 0;
|
---|
700 | int exe_flag = 0;
|
---|
701 | int map_flag = 0;
|
---|
702 | int stack_size = 0;
|
---|
703 | int emxbind_strip = 0;
|
---|
704 | enum exe_bind_type
|
---|
705 | {
|
---|
706 | EMX_DEFAULT, RSXNT_WIN32, RSXNT_RSX, RSXNT_EMX
|
---|
707 | } rsxnt_linked = EMX_DEFAULT;
|
---|
708 |
|
---|
709 | /* What kind of output file to write. */
|
---|
710 |
|
---|
711 | enum file_type output_file_type;
|
---|
712 |
|
---|
713 | #ifndef DEFAULT_OUTPUT_FILE_TYPE
|
---|
714 | #define DEFAULT_OUTPUT_FILE_TYPE IS_A_OUT
|
---|
715 | #endif
|
---|
716 |
|
---|
717 | /* What `style' of output file to write. For BSD a.out files
|
---|
718 | this specifies OMAGIC, NMAGIC, or ZMAGIC. For Mach-O files
|
---|
719 | this switches between MH_OBJECT and two flavors of MH_EXECUTE. */
|
---|
720 |
|
---|
721 | enum output_style
|
---|
722 | {
|
---|
723 | OUTPUT_UNSPECIFIED,
|
---|
724 | OUTPUT_RELOCATABLE, /* -r */
|
---|
725 | OUTPUT_WRITABLE_TEXT, /* -N */
|
---|
726 | OUTPUT_READONLY_TEXT, /* -n */
|
---|
727 | OUTPUT_DEMAND_PAGED /* -Z (default) */
|
---|
728 | };
|
---|
729 |
|
---|
730 | enum output_style output_style;
|
---|
731 |
|
---|
732 | #ifndef DEFAULT_OUTPUT_STYLE
|
---|
733 | #define DEFAULT_OUTPUT_STYLE OUTPUT_DEMAND_PAGED
|
---|
734 | #endif
|
---|
735 |
|
---|
736 | /* Descriptor for writing that file with `mywrite'. */
|
---|
737 |
|
---|
738 | int outdesc;
|
---|
739 |
|
---|
740 | /* The following are computed by `digest_symbols'. */
|
---|
741 |
|
---|
742 | int text_size; /* total size of text of all input files. */
|
---|
743 | int text_header_size; /* size of the file header if included in the
|
---|
744 | text size. */
|
---|
745 | int data_size; /* total size of data of all input files. */
|
---|
746 | int bss_size; /* total size of bss of all input files. */
|
---|
747 | int text_reloc_size; /* total size of text relocation of all input files. */
|
---|
748 | int data_reloc_size; /* total size of data relocation of all input
|
---|
749 | files. */
|
---|
750 |
|
---|
751 | /* The following are computed by write_header(). */
|
---|
752 | long int output_text_offset; /* file offset of the text section. */
|
---|
753 | long int output_data_offset; /* file offset of the data section. */
|
---|
754 | long int output_trel_offset; /* file offset of the text relocation info. */
|
---|
755 | long int output_drel_offset; /* file offset of the data relocation info. */
|
---|
756 | long int output_syms_offset; /* file offset of the symbol table. */
|
---|
757 | long int output_strs_offset; /* file offset of the string table. */
|
---|
758 |
|
---|
759 | /* The following are incrementally computed by write_syms(); we keep
|
---|
760 | them here so we can examine their values afterwards. */
|
---|
761 | unsigned int output_syms_size; /* total bytes of symbol table output. */
|
---|
762 | unsigned int output_strs_size; /* total bytes of string table output. */
|
---|
763 |
|
---|
764 | /* This can only be computed after the size of the string table is known. */
|
---|
765 | long int output_symseg_offset; /* file offset of the symbol segment (if any). */
|
---|
766 |
|
---|
767 | /* Incrementally computed by write_file_symseg(). */
|
---|
768 | unsigned int output_symseg_size;
|
---|
769 |
|
---|
770 | /* Specifications of start and length of the area reserved at the end
|
---|
771 | of the text segment for the set vectors. Computed in 'digest_symbols' */
|
---|
772 | int set_sect_start;
|
---|
773 | int set_sect_size;
|
---|
774 |
|
---|
775 | /* Pointer for in core storage for the above vectors, before they are
|
---|
776 | written. */
|
---|
777 | unsigned long *set_vectors;
|
---|
778 |
|
---|
779 | int *set_reloc;
|
---|
780 |
|
---|
781 | /* Amount of cleared space to leave at the end of the text segment. */
|
---|
782 |
|
---|
783 | int text_pad;
|
---|
784 |
|
---|
785 | /* Amount of padding between data segment and set vectors. */
|
---|
786 | int set_sect_pad;
|
---|
787 |
|
---|
788 | /* Amount of padding at end of data segment. This has two parts:
|
---|
789 | That which is before the bss segment, and that which overlaps
|
---|
790 | with the bss segment. */
|
---|
791 | int data_pad;
|
---|
792 |
|
---|
793 | /* Format of __.SYMDEF:
|
---|
794 | First, a longword containing the size of the 'symdef' data that follows.
|
---|
795 | Second, zero or more 'symdef' structures.
|
---|
796 | Third, a longword containing the length of symbol name strings.
|
---|
797 | Fourth, zero or more symbol name strings (each followed by a null). */
|
---|
798 |
|
---|
799 | struct symdef {
|
---|
800 | int symbol_name_string_index;
|
---|
801 | int library_member_offset;
|
---|
802 | };
|
---|
803 | |
---|
804 |
|
---|
805 | /* Record most of the command options. */
|
---|
806 |
|
---|
807 | /* Address we assume the text section will be loaded at.
|
---|
808 | We relocate symbols and text and data for this, but we do not
|
---|
809 | write any padding in the output file for it. */
|
---|
810 | int text_start;
|
---|
811 |
|
---|
812 | /* Address we decide the data section will be loaded at. */
|
---|
813 | int data_start;
|
---|
814 |
|
---|
815 | /* Nonzero if -T was specified in the command line.
|
---|
816 | This prevents text_start from being set later to default values. */
|
---|
817 | int T_flag_specified;
|
---|
818 |
|
---|
819 | /* Nonzero if -Tdata was specified in the command line.
|
---|
820 | This prevents data_start from being set later to default values. */
|
---|
821 | int Tdata_flag_specified;
|
---|
822 |
|
---|
823 | /* Size to pad data section up to.
|
---|
824 | We simply increase the size of the data section, padding with zeros,
|
---|
825 | and reduce the size of the bss section to match. */
|
---|
826 | int specified_data_size;
|
---|
827 |
|
---|
828 | /* Nonzero means print names of input files as processed. */
|
---|
829 | int trace_files;
|
---|
830 |
|
---|
831 | /* Which symbols should be stripped (omitted from the output):
|
---|
832 | none, all, or debugger symbols. */
|
---|
833 | enum { STRIP_NONE, STRIP_ALL, STRIP_DEBUGGER } strip_symbols;
|
---|
834 |
|
---|
835 | /* Which local symbols should be omitted:
|
---|
836 | none, all, or those starting with L.
|
---|
837 | This is irrelevant if STRIP_NONE. */
|
---|
838 | enum { DISCARD_NONE, DISCARD_ALL, DISCARD_L } discard_locals;
|
---|
839 |
|
---|
840 | /* 1 => write load map. */
|
---|
841 | int write_map;
|
---|
842 |
|
---|
843 | /* 1 => assign space to common symbols even if OUTPUT_RELOCATABLE. */
|
---|
844 | int force_common_definition;
|
---|
845 |
|
---|
846 | /* Standard directories to search for files specified by -l. */
|
---|
847 | char *standard_search_dirs[] = { "/usr/lib" };
|
---|
848 |
|
---|
849 | /* If set STANDARD_SEARCH_DIRS is not searched. */
|
---|
850 | int no_standard_dirs;
|
---|
851 |
|
---|
852 | /* Actual vector of directories to search;
|
---|
853 | this contains those specified with -L plus the standard ones. */
|
---|
854 | char **search_dirs;
|
---|
855 |
|
---|
856 | /* Length of the vector `search_dirs'. */
|
---|
857 | int n_search_dirs;
|
---|
858 |
|
---|
859 | /* Non zero means to create the output executable.
|
---|
860 | Cleared by nonfatal errors. */
|
---|
861 | int make_executable;
|
---|
862 |
|
---|
863 | /* Force the executable to be output, even if there are non-fatal
|
---|
864 | errors */
|
---|
865 | int force_executable;
|
---|
866 |
|
---|
867 | /* Whether or not to include .dll in the shared library searching. */
|
---|
868 | int opt_dll_search;
|
---|
869 |
|
---|
870 | /* Keep a list of any symbols referenced from the command line (so
|
---|
871 | that error messages for these guys can be generated). This list is
|
---|
872 | zero terminated. */
|
---|
873 | struct glosym **cmdline_references;
|
---|
874 | int cl_refs_allocated;
|
---|
875 |
|
---|
876 | void *xmalloc (size_t);
|
---|
877 | void *xrealloc (void *, size_t);
|
---|
878 | void usage (char *, char *);
|
---|
879 | void fatal (char *, ...);
|
---|
880 | void fatal_with_file (char *, struct file_entry *);
|
---|
881 | void perror_name (char *);
|
---|
882 | void perror_file (struct file_entry *);
|
---|
883 | void error (char *, char *, char *, char *);
|
---|
884 |
|
---|
885 | int parse (char *, char *, char *);
|
---|
886 | void initialize_text_start (void);
|
---|
887 | void initialize_data_start (void);
|
---|
888 | void digest_symbols (void);
|
---|
889 | void print_symbols (FILE *);
|
---|
890 | void load_symbols (void);
|
---|
891 | void decode_command (int, char **);
|
---|
892 | void write_output (void);
|
---|
893 | void write_header (void);
|
---|
894 | void write_text (void);
|
---|
895 | void read_file_relocation (struct file_entry *);
|
---|
896 | void write_data (void);
|
---|
897 | void write_rel (void);
|
---|
898 | void write_syms (void);
|
---|
899 | void write_symsegs (void);
|
---|
900 | void mywrite (void *, int, int, int);
|
---|
901 | void symtab_init (void);
|
---|
902 | void padfile (int, int);
|
---|
903 | char *get_file_name (struct file_entry *);
|
---|
904 | symbol *getsym (char *), *getsym_soft (char *);
|
---|
905 | void do_warnings (FILE *);
|
---|
906 | void check_exe (void);
|
---|
907 | char *lx_to_aout (const char *pszFilename);
|
---|
908 | int check_lx_dll(int fd);
|
---|
909 | void cleanup (void);
|
---|
910 |
|
---|
911 | void add_cmdline_ref (struct glosym *sp);
|
---|
912 | void prline_file_name (struct file_entry *entry, FILE *outfile);
|
---|
913 | void deduce_file_type(int desc, struct file_entry *entry);
|
---|
914 | void read_a_out_header (int desc, struct file_entry *entry);
|
---|
915 | void read_header (int desc, struct file_entry *entry);
|
---|
916 | void read_entry_symbols (int desc, struct file_entry *entry);
|
---|
917 | void read_entry_strings (int desc, struct file_entry *entry);
|
---|
918 | unsigned long contains_symbol (struct file_entry *entry, struct nlist *n_ptr);
|
---|
919 | void process_subentry (int desc, struct file_entry *subentry, struct file_entry *entry, struct file_entry **prev_addr);
|
---|
920 | void consider_file_section_lengths (struct file_entry *entry);
|
---|
921 | void relocate_file_addresses (struct file_entry *entry);
|
---|
922 | void describe_file_sections (struct file_entry *entry, FILE *outfile);
|
---|
923 | void list_file_locals (struct file_entry *entry, FILE *outfile);
|
---|
924 | int relocation_entries_relation (struct relocation_info *rel1, struct relocation_info *rel2);
|
---|
925 | void do_relocation_warnings (struct file_entry *entry, int data_segment, FILE *outfile, unsigned char *nlist_bitvector);
|
---|
926 | void do_file_warnings (struct file_entry *entry, FILE *outfile);
|
---|
927 | void initialize_a_out_text_start (void);
|
---|
928 | void initialize_a_out_data_start (void);
|
---|
929 | void compute_a_out_section_offsets (void);
|
---|
930 | void compute_more_a_out_section_offsets (void);
|
---|
931 | void write_a_out_header (void);
|
---|
932 | int hash_string (char *key);
|
---|
933 | void read_file_symbols (struct file_entry *entry);
|
---|
934 | void compute_section_offsets (void);
|
---|
935 | void compute_more_section_offsets (void);
|
---|
936 | void read_relocation (void);
|
---|
937 | int assign_string_table_index (char *name);
|
---|
938 | unsigned long check_each_file (register unsigned long (*function)(), register int arg);
|
---|
939 | static void gen_deffile (void);
|
---|
940 |
|
---|
941 |
|
---|
942 |
|
---|
943 | |
---|
944 |
|
---|
945 | int
|
---|
946 | main (argc, argv)
|
---|
947 | char **argv;
|
---|
948 | int argc;
|
---|
949 | {
|
---|
950 | _response (&argc, &argv);
|
---|
951 | _wildcard (&argc, &argv);
|
---|
952 | page_size = getpagesize ();
|
---|
953 | progname = argv[0];
|
---|
954 |
|
---|
955 | #ifdef RLIMIT_STACK
|
---|
956 | /* Avoid dumping core on large .o files. */
|
---|
957 | {
|
---|
958 | struct rlimit rl;
|
---|
959 |
|
---|
960 | getrlimit (RLIMIT_STACK, &rl);
|
---|
961 | rl.rlim_cur = rl.rlim_max;
|
---|
962 | setrlimit (RLIMIT_STACK, &rl);
|
---|
963 | }
|
---|
964 | #endif
|
---|
965 |
|
---|
966 | /* Clear the cumulative info on the output file. */
|
---|
967 |
|
---|
968 | text_size = 0;
|
---|
969 | data_size = 0;
|
---|
970 | bss_size = 0;
|
---|
971 | text_reloc_size = 0;
|
---|
972 | data_reloc_size = 0;
|
---|
973 |
|
---|
974 | set_sect_pad = 0;
|
---|
975 | data_pad = 0;
|
---|
976 | text_pad = 0;
|
---|
977 |
|
---|
978 | /* Initialize the data about options. */
|
---|
979 |
|
---|
980 | specified_data_size = 0;
|
---|
981 | strip_symbols = STRIP_NONE;
|
---|
982 | trace_files = 0;
|
---|
983 | discard_locals = DISCARD_NONE;
|
---|
984 | entry_symbol = 0;
|
---|
985 | write_map = 0;
|
---|
986 | force_common_definition = 0;
|
---|
987 | T_flag_specified = 0;
|
---|
988 | Tdata_flag_specified = 0;
|
---|
989 | make_executable = 1;
|
---|
990 | force_executable = 0;
|
---|
991 | set_element_prefixes = 0;
|
---|
992 |
|
---|
993 | /* Initialize the cumulative counts of symbols. */
|
---|
994 |
|
---|
995 | local_sym_count = 0;
|
---|
996 | non_L_local_sym_count = 0;
|
---|
997 | debugger_sym_count = 0;
|
---|
998 | undefined_global_sym_count = 0;
|
---|
999 | set_symbol_count = 0;
|
---|
1000 | set_vector_count = 0;
|
---|
1001 | global_indirect_count = 0;
|
---|
1002 | warning_count = 0;
|
---|
1003 | multiple_def_count = 0;
|
---|
1004 | common_defined_global_count = 0;
|
---|
1005 |
|
---|
1006 | /* Keep a list of symbols referenced from the command line */
|
---|
1007 |
|
---|
1008 | cl_refs_allocated = 10;
|
---|
1009 | cmdline_references
|
---|
1010 | = (struct glosym **) xmalloc (cl_refs_allocated
|
---|
1011 | * sizeof(struct glosym *));
|
---|
1012 | *cmdline_references = 0;
|
---|
1013 |
|
---|
1014 | /* Cleanup converted file on exit. */
|
---|
1015 |
|
---|
1016 | atexit (cleanup);
|
---|
1017 |
|
---|
1018 | /* Completely decode ARGV. */
|
---|
1019 |
|
---|
1020 | decode_command (argc, argv);
|
---|
1021 |
|
---|
1022 | check_exe ();
|
---|
1023 |
|
---|
1024 | /* Load symbols of all input files.
|
---|
1025 | Also search all libraries and decide which library members to load. */
|
---|
1026 |
|
---|
1027 | load_symbols ();
|
---|
1028 |
|
---|
1029 | /* Create various built-in symbols. This must occur after
|
---|
1030 | all input files are loaded so that a user program can have a
|
---|
1031 | symbol named etext (for example). */
|
---|
1032 |
|
---|
1033 | if (output_style != OUTPUT_RELOCATABLE)
|
---|
1034 | symtab_init ();
|
---|
1035 |
|
---|
1036 | /* Compute where each file's sections go, and relocate symbols. */
|
---|
1037 |
|
---|
1038 | digest_symbols ();
|
---|
1039 |
|
---|
1040 | /* Print error messages for any missing symbols, for any warning
|
---|
1041 | symbols, and possibly multiple definitions */
|
---|
1042 |
|
---|
1043 | do_warnings (stderr);
|
---|
1044 |
|
---|
1045 | /* Print a map, if requested. */
|
---|
1046 |
|
---|
1047 | if (write_map) print_symbols (stdout);
|
---|
1048 |
|
---|
1049 | /* Write the output file. */
|
---|
1050 |
|
---|
1051 | if (make_executable || force_executable)
|
---|
1052 | write_output ();
|
---|
1053 |
|
---|
1054 | exit (!make_executable);
|
---|
1055 | }
|
---|
1056 | |
---|
1057 |
|
---|
1058 | void add_cmdline_ref ();
|
---|
1059 |
|
---|
1060 | static struct option longopts[] =
|
---|
1061 | {
|
---|
1062 | {"d", 0, 0, 'd'},
|
---|
1063 | {"dc", 0, 0, 'd'}, /* For Sun compatibility. */
|
---|
1064 | {"dp", 0, 0, 'd'}, /* For Sun compatibility. */
|
---|
1065 | {"e", 1, 0, 'e'},
|
---|
1066 | {"n", 0, 0, 'n'},
|
---|
1067 | {"noinhibit-exec", 0, 0, 130},
|
---|
1068 | {"nostdlib", 0, 0, 133},
|
---|
1069 | {"o", 1, 0, 'o'},
|
---|
1070 | {"r", 0, 0, 'r'},
|
---|
1071 | {"s", 0, 0, 's'},
|
---|
1072 | {"t", 0, 0, 't'},
|
---|
1073 | {"u", 1, 0, 'u'},
|
---|
1074 | {"x", 0, 0, 'x'},
|
---|
1075 | {"z", 0, 0, 'z'},
|
---|
1076 | {"A", 1, 0, 'A'},
|
---|
1077 | {"D", 1, 0, 'D'},
|
---|
1078 | {"M", 0, 0, 'M'},
|
---|
1079 | {"N", 0, 0, 'N'},
|
---|
1080 | {"R", 0, 0, 'R'}, /* Create relocatable executable */
|
---|
1081 | {"Zexe", 0, 0, 135}, /* Create .exe file, touch `output file' */
|
---|
1082 | {"Zstack", 1, 0, 136}, /* Set stack size */
|
---|
1083 | {"Zmap", 2, 0, 137}, /* Create .map file */
|
---|
1084 | {"Zno-demangle", 0, 0, 138}, /* Don't demangle symbols */
|
---|
1085 | {"Zdemangle-proto", 0, 0, 139}, /* Demangle symbols complete */
|
---|
1086 | {"Zwin32", 0, 0, 140}, /* Create GUI, CUI Win32 */
|
---|
1087 | {"Zrsx32", 0, 0, 141}, /* Create Win32/DOS win32 base */
|
---|
1088 | {"Zemx32", 0, 0, 142}, /* Create Win32/DOS emx base */
|
---|
1089 | {"S", 0, 0, 'S'},
|
---|
1090 | {"T", 1, 0, 'T'},
|
---|
1091 | {"Ttext", 1, 0, 'T'},
|
---|
1092 | {"Tdata", 1, 0, 132},
|
---|
1093 | {"V", 1, 0, 'V'},
|
---|
1094 | {"X", 0, 0, 'X'},
|
---|
1095 | #define OPT_LIBS_STATIC 0x1000
|
---|
1096 | {"Bstatic", 0, 0, OPT_LIBS_STATIC},
|
---|
1097 | {"non_shared", 0, 0, OPT_LIBS_STATIC},
|
---|
1098 | {"dn", 0, 0, OPT_LIBS_STATIC},
|
---|
1099 | {"static", 0, 0, OPT_LIBS_STATIC},
|
---|
1100 | #define OPT_LIBS_SHARED 0x1001
|
---|
1101 | {"Bshared", 0, 0, OPT_LIBS_SHARED},
|
---|
1102 | {"call_shared", 0, 0, OPT_LIBS_SHARED},
|
---|
1103 | {"dy", 0, 0, OPT_LIBS_SHARED},
|
---|
1104 | #define OPT_ZDLL_SEARCH 0x1008
|
---|
1105 | {"Zdll-search",0, 0, OPT_ZDLL_SEARCH},
|
---|
1106 | {0, 0, 0, 0}
|
---|
1107 | };
|
---|
1108 |
|
---|
1109 | /* Since the Unix ld accepts -lfoo, -Lfoo, and -yfoo, we must also.
|
---|
1110 | This effectively prevents any long options from starting with
|
---|
1111 | one of these letters. */
|
---|
1112 | #define SHORTOPTS "-l:y:L:"
|
---|
1113 |
|
---|
1114 | /* Process the command arguments,
|
---|
1115 | setting up file_table with an entry for each input file,
|
---|
1116 | and setting variables according to the options. */
|
---|
1117 |
|
---|
1118 | void
|
---|
1119 | decode_command (argc, argv)
|
---|
1120 | char **argv;
|
---|
1121 | int argc;
|
---|
1122 | {
|
---|
1123 | int optc, longind;
|
---|
1124 | register struct file_entry *p;
|
---|
1125 | int opt_libs_static = 0;
|
---|
1126 |
|
---|
1127 | number_of_files = 0;
|
---|
1128 | output_filename = "a.out";
|
---|
1129 |
|
---|
1130 | n_search_dirs = 0;
|
---|
1131 | search_dirs = (char **) xmalloc (sizeof (char *));
|
---|
1132 |
|
---|
1133 | /* First compute number_of_files so we know how long to make file_table.
|
---|
1134 | Also process most options completely. */
|
---|
1135 |
|
---|
1136 | while ((optc = getopt_long_only (argc, argv, SHORTOPTS, longopts, &longind))
|
---|
1137 | != EOF)
|
---|
1138 | {
|
---|
1139 | if (optc == 0)
|
---|
1140 | optc = longopts[longind].val;
|
---|
1141 |
|
---|
1142 | switch (optc)
|
---|
1143 | {
|
---|
1144 | case '?':
|
---|
1145 | usage (0, 0);
|
---|
1146 | break;
|
---|
1147 |
|
---|
1148 | case 1:
|
---|
1149 | /* Non-option argument. */
|
---|
1150 | number_of_files++;
|
---|
1151 | break;
|
---|
1152 |
|
---|
1153 | case 'd':
|
---|
1154 | force_common_definition = 1;
|
---|
1155 | break;
|
---|
1156 |
|
---|
1157 | case 'e':
|
---|
1158 | entry_symbol = getsym (optarg);
|
---|
1159 | if (!entry_symbol->defined && !entry_symbol->referenced)
|
---|
1160 | undefined_global_sym_count++;
|
---|
1161 | entry_symbol->referenced = 1;
|
---|
1162 | add_cmdline_ref (entry_symbol);
|
---|
1163 | break;
|
---|
1164 |
|
---|
1165 | case 'l':
|
---|
1166 | number_of_files++;
|
---|
1167 | break;
|
---|
1168 |
|
---|
1169 | case 'n':
|
---|
1170 | if (output_style && output_style != OUTPUT_READONLY_TEXT)
|
---|
1171 | fatal ("illegal combination of -n with -N, -r, or -z", (char *) 0);
|
---|
1172 | output_style = OUTPUT_READONLY_TEXT;
|
---|
1173 | break;
|
---|
1174 |
|
---|
1175 | case 130: /* -noinhibit-exec */
|
---|
1176 | force_executable = 1;
|
---|
1177 | break;
|
---|
1178 |
|
---|
1179 | case 133: /* -nostdlib */
|
---|
1180 | no_standard_dirs = 1;
|
---|
1181 | break;
|
---|
1182 |
|
---|
1183 | case 'o':
|
---|
1184 | output_filename = optarg;
|
---|
1185 | break;
|
---|
1186 |
|
---|
1187 | case 'r':
|
---|
1188 | if (output_style && output_style != OUTPUT_RELOCATABLE)
|
---|
1189 | fatal ("illegal combination of -r with -N, -n, or -z", (char *) 0);
|
---|
1190 | output_style = OUTPUT_RELOCATABLE;
|
---|
1191 | text_start = 0;
|
---|
1192 | break;
|
---|
1193 |
|
---|
1194 | case 's':
|
---|
1195 | strip_symbols = STRIP_ALL;
|
---|
1196 | break;
|
---|
1197 |
|
---|
1198 | case 't':
|
---|
1199 | trace_files = 1;
|
---|
1200 | break;
|
---|
1201 |
|
---|
1202 | case 'u':
|
---|
1203 | {
|
---|
1204 | register symbol *sp = getsym (optarg);
|
---|
1205 |
|
---|
1206 | if (!sp->defined && !sp->referenced)
|
---|
1207 | undefined_global_sym_count++;
|
---|
1208 | sp->referenced = 1;
|
---|
1209 | add_cmdline_ref (sp);
|
---|
1210 | }
|
---|
1211 | break;
|
---|
1212 |
|
---|
1213 | case 'x':
|
---|
1214 | discard_locals = DISCARD_ALL;
|
---|
1215 | break;
|
---|
1216 |
|
---|
1217 | case 'y':
|
---|
1218 | {
|
---|
1219 | register symbol *sp = getsym (optarg);
|
---|
1220 |
|
---|
1221 | sp->trace = 1;
|
---|
1222 | }
|
---|
1223 | break;
|
---|
1224 |
|
---|
1225 | case 'z':
|
---|
1226 | if (output_style && output_style != OUTPUT_DEMAND_PAGED)
|
---|
1227 | fatal ("illegal combination of -z with -N, -n, or -r", (char *) 0);
|
---|
1228 | output_style = OUTPUT_DEMAND_PAGED;
|
---|
1229 | break;
|
---|
1230 |
|
---|
1231 | case 'A':
|
---|
1232 | number_of_files++;
|
---|
1233 | break;
|
---|
1234 |
|
---|
1235 | case 'D':
|
---|
1236 | specified_data_size = parse (optarg, "%x", "invalid argument to -D");
|
---|
1237 | break;
|
---|
1238 |
|
---|
1239 | case 'L':
|
---|
1240 | n_search_dirs++;
|
---|
1241 | search_dirs = (char **)
|
---|
1242 | xrealloc (search_dirs, n_search_dirs * sizeof (char *));
|
---|
1243 | search_dirs[n_search_dirs - 1] = optarg;
|
---|
1244 | break;
|
---|
1245 |
|
---|
1246 | case 'M':
|
---|
1247 | write_map = 1;
|
---|
1248 | break;
|
---|
1249 |
|
---|
1250 | case 'N':
|
---|
1251 | if (output_style && output_style != OUTPUT_WRITABLE_TEXT)
|
---|
1252 | fatal ("illegal combination of -N with -n, -r, or -z", (char *) 0);
|
---|
1253 | output_style = OUTPUT_WRITABLE_TEXT;
|
---|
1254 | break;
|
---|
1255 |
|
---|
1256 | case 135: /* -Zexe */
|
---|
1257 | exe_flag = 1;
|
---|
1258 | break;
|
---|
1259 |
|
---|
1260 | case 136: /* -Zstack */
|
---|
1261 | stack_size = parse (optarg, "%i", "invalid argument to -Zstack");
|
---|
1262 | break;
|
---|
1263 |
|
---|
1264 | case 137: /* -Zmap */
|
---|
1265 | map_filename = optarg;
|
---|
1266 | map_flag = 1;
|
---|
1267 | break;
|
---|
1268 |
|
---|
1269 | case 138: /* -Zno-demangle */
|
---|
1270 | demangler = 0;
|
---|
1271 | break;
|
---|
1272 |
|
---|
1273 | case 139: /* -Zdemangle-proto */
|
---|
1274 | demangle_options = DMGL_PARAMS | DMGL_ANSI;
|
---|
1275 | break;
|
---|
1276 |
|
---|
1277 | case 140: /* -Zwin32: GUI,CUI Win32 */
|
---|
1278 | rsxnt_linked = RSXNT_WIN32;
|
---|
1279 | break;
|
---|
1280 |
|
---|
1281 | case 141: /* -Zrsx32: Win32/DOS win32 base */
|
---|
1282 | rsxnt_linked = RSXNT_RSX;
|
---|
1283 | break;
|
---|
1284 |
|
---|
1285 | case 142: /* -Zemx32: Win32/DOS emx base */
|
---|
1286 | rsxnt_linked = RSXNT_EMX;
|
---|
1287 | break;
|
---|
1288 |
|
---|
1289 | case 'R':
|
---|
1290 | reloc_flag = 1;
|
---|
1291 | break;
|
---|
1292 |
|
---|
1293 | case 'S':
|
---|
1294 | strip_symbols = STRIP_DEBUGGER;
|
---|
1295 | break;
|
---|
1296 |
|
---|
1297 | case 'T':
|
---|
1298 | text_start = parse (optarg, "%x", "invalid argument to -Ttext");
|
---|
1299 | T_flag_specified = 1;
|
---|
1300 | break;
|
---|
1301 |
|
---|
1302 | case 132: /* -Tdata addr */
|
---|
1303 | data_start = parse (optarg, "%x", "invalid argument to -Tdata");
|
---|
1304 | Tdata_flag_specified = 1;
|
---|
1305 | break;
|
---|
1306 |
|
---|
1307 | case 'V':
|
---|
1308 | {
|
---|
1309 | struct string_list_element *new
|
---|
1310 | = (struct string_list_element *)
|
---|
1311 | xmalloc (sizeof (struct string_list_element));
|
---|
1312 |
|
---|
1313 | new->str = optarg;
|
---|
1314 | new->next = set_element_prefixes;
|
---|
1315 | set_element_prefixes = new;
|
---|
1316 | }
|
---|
1317 | break;
|
---|
1318 |
|
---|
1319 | case 'X':
|
---|
1320 | discard_locals = DISCARD_L;
|
---|
1321 | break;
|
---|
1322 |
|
---|
1323 | case OPT_ZDLL_SEARCH:
|
---|
1324 | opt_dll_search = 1;
|
---|
1325 | break;
|
---|
1326 |
|
---|
1327 | case OPT_LIBS_STATIC:
|
---|
1328 | case OPT_LIBS_SHARED:
|
---|
1329 | /* processed later */
|
---|
1330 | break;
|
---|
1331 | }
|
---|
1332 | }
|
---|
1333 |
|
---|
1334 | if (!number_of_files)
|
---|
1335 | usage ("no input files", 0);
|
---|
1336 |
|
---|
1337 | p = file_table
|
---|
1338 | = (struct file_entry *) xmalloc (number_of_files * sizeof (struct file_entry));
|
---|
1339 | bzero (p, number_of_files * sizeof (struct file_entry));
|
---|
1340 |
|
---|
1341 | /* Now scan again and fill in file_table.
|
---|
1342 | All options except -A and -l are ignored here. */
|
---|
1343 |
|
---|
1344 | optind = 0; /* Reset getopt. */
|
---|
1345 | while ((optc = getopt_long_only (argc, argv, SHORTOPTS, longopts, &longind))
|
---|
1346 | != EOF)
|
---|
1347 | {
|
---|
1348 | if (optc == 0)
|
---|
1349 | optc = longopts[longind].val;
|
---|
1350 |
|
---|
1351 | switch (optc)
|
---|
1352 | {
|
---|
1353 | case 1:
|
---|
1354 | /* Non-option argument. */
|
---|
1355 | {
|
---|
1356 | char *ext = _getext (optarg);
|
---|
1357 | if (ext != NULL && stricmp (ext, ".def") == 0
|
---|
1358 | && def_filename == NULL)
|
---|
1359 | {
|
---|
1360 | def_filename = optarg;
|
---|
1361 | --number_of_files;
|
---|
1362 | break;
|
---|
1363 | }
|
---|
1364 | else if (ext != NULL && stricmp (ext, ".res") == 0
|
---|
1365 | && res_filename == NULL)
|
---|
1366 | {
|
---|
1367 | res_filename = optarg;
|
---|
1368 | --number_of_files;
|
---|
1369 | break;
|
---|
1370 | }
|
---|
1371 | else if (ext != NULL && stricmp (ext, ".dll") == 0
|
---|
1372 | && res_filename == NULL)
|
---|
1373 | { /* convert .dll to temporary import library. */
|
---|
1374 | p->filename = lx_to_aout (optarg);
|
---|
1375 | p->local_sym_name = optarg;
|
---|
1376 | p++;
|
---|
1377 | break;
|
---|
1378 | }
|
---|
1379 | }
|
---|
1380 | p->filename = optarg;
|
---|
1381 | p->local_sym_name = optarg;
|
---|
1382 | p++;
|
---|
1383 | break;
|
---|
1384 |
|
---|
1385 | case 'A':
|
---|
1386 | if (p != file_table)
|
---|
1387 | usage ("-A specified before an input file other than the first", NULL);
|
---|
1388 | p->filename = optarg;
|
---|
1389 | p->local_sym_name = optarg;
|
---|
1390 | p->just_syms_flag = 1;
|
---|
1391 | p++;
|
---|
1392 | break;
|
---|
1393 |
|
---|
1394 | case 'l':
|
---|
1395 | p->filename = concat ("", optarg, "", NULL);
|
---|
1396 | p->local_sym_name = concat ("-l", optarg, "", NULL);
|
---|
1397 | p->search_dirs_flag = 1;
|
---|
1398 | p->dynamic = !opt_libs_static;
|
---|
1399 | p++;
|
---|
1400 | break;
|
---|
1401 |
|
---|
1402 | case OPT_LIBS_STATIC:
|
---|
1403 | opt_libs_static = 1;
|
---|
1404 | break;
|
---|
1405 | case OPT_LIBS_SHARED:
|
---|
1406 | opt_libs_static = 0;
|
---|
1407 | break;
|
---|
1408 | }
|
---|
1409 | }
|
---|
1410 |
|
---|
1411 | if (!output_file_type)
|
---|
1412 | output_file_type = DEFAULT_OUTPUT_FILE_TYPE;
|
---|
1413 |
|
---|
1414 | if (!output_style)
|
---|
1415 | output_style = DEFAULT_OUTPUT_STYLE;
|
---|
1416 |
|
---|
1417 | #if 0
|
---|
1418 | /* THIS CONSISTENCY CHECK BELONGS SOMEWHERE ELSE. */
|
---|
1419 | /* Now check some option settings for consistency. */
|
---|
1420 |
|
---|
1421 | if ((output_style == OUTPUT_READONLY_TEXT || output_style == OUTPUT_DEMAND_PAGED)
|
---|
1422 | && (text_start - text_start_alignment) & (page_size - 1))
|
---|
1423 | usage ("-T argument not multiple of page size, with sharable output", 0);
|
---|
1424 | #endif
|
---|
1425 |
|
---|
1426 | /* Append the standard search directories to the user-specified ones. */
|
---|
1427 | if (!no_standard_dirs)
|
---|
1428 | {
|
---|
1429 | int n = sizeof standard_search_dirs / sizeof standard_search_dirs[0];
|
---|
1430 | n_search_dirs += n;
|
---|
1431 | search_dirs
|
---|
1432 | = (char **) xrealloc (search_dirs, n_search_dirs * sizeof (char *));
|
---|
1433 | bcopy (standard_search_dirs, &search_dirs[n_search_dirs - n],
|
---|
1434 | n * sizeof (char *));
|
---|
1435 | }
|
---|
1436 | }
|
---|
1437 | |
---|
1438 |
|
---|
1439 |
|
---|
1440 | void
|
---|
1441 | add_cmdline_ref (sp)
|
---|
1442 | struct glosym *sp;
|
---|
1443 | {
|
---|
1444 | struct glosym **ptr;
|
---|
1445 |
|
---|
1446 | for (ptr = cmdline_references;
|
---|
1447 | ptr < cmdline_references + cl_refs_allocated && *ptr;
|
---|
1448 | ptr++)
|
---|
1449 | ;
|
---|
1450 |
|
---|
1451 | if (ptr >= cmdline_references + cl_refs_allocated - 1)
|
---|
1452 | {
|
---|
1453 | int diff = ptr - cmdline_references;
|
---|
1454 |
|
---|
1455 | cl_refs_allocated *= 2;
|
---|
1456 | cmdline_references = (struct glosym **)
|
---|
1457 | xrealloc (cmdline_references,
|
---|
1458 | cl_refs_allocated * sizeof (struct glosym *));
|
---|
1459 | ptr = cmdline_references + diff;
|
---|
1460 | }
|
---|
1461 |
|
---|
1462 | *ptr++ = sp;
|
---|
1463 | *ptr = (struct glosym *) 0;
|
---|
1464 | }
|
---|
1465 |
|
---|
1466 | static int
|
---|
1467 | set_element_prefixed_p (name)
|
---|
1468 | char *name;
|
---|
1469 | {
|
---|
1470 | struct string_list_element *p;
|
---|
1471 | int i;
|
---|
1472 |
|
---|
1473 | for (p = set_element_prefixes; p; p = p->next)
|
---|
1474 | {
|
---|
1475 | for (i = 0; p->str[i] != '\0' && (p->str[i] == name[i]); i++)
|
---|
1476 | ;
|
---|
1477 |
|
---|
1478 | if (p->str[i] == '\0')
|
---|
1479 | return 1;
|
---|
1480 | }
|
---|
1481 | return 0;
|
---|
1482 | }
|
---|
1483 | |
---|
1484 |
|
---|
1485 | /* Convenient functions for operating on one or all files being
|
---|
1486 | loaded. */
|
---|
1487 | void print_file_name (struct file_entry *entry, FILE *outfile);
|
---|
1488 |
|
---|
1489 | /* Call FUNCTION on each input file entry.
|
---|
1490 | Do not call for entries for libraries;
|
---|
1491 | instead, call once for each library member that is being loaded.
|
---|
1492 |
|
---|
1493 | FUNCTION receives two arguments: the entry, and ARG. */
|
---|
1494 |
|
---|
1495 | static void
|
---|
1496 | each_file (function, arg)
|
---|
1497 | register void (*function)();
|
---|
1498 | register int arg;
|
---|
1499 | {
|
---|
1500 | register int i;
|
---|
1501 |
|
---|
1502 | for (i = 0; i < number_of_files; i++)
|
---|
1503 | {
|
---|
1504 | register struct file_entry *entry = &file_table[i];
|
---|
1505 | if (entry->library_flag)
|
---|
1506 | {
|
---|
1507 | register struct file_entry *subentry = entry->subfiles;
|
---|
1508 | for (; subentry; subentry = subentry->chain)
|
---|
1509 | (*function) (subentry, arg);
|
---|
1510 | }
|
---|
1511 | else
|
---|
1512 | (*function) (entry, arg);
|
---|
1513 | }
|
---|
1514 | }
|
---|
1515 |
|
---|
1516 | /* Call FUNCTION on each input file entry until it returns a non-zero
|
---|
1517 | value. Return this value.
|
---|
1518 | Do not call for entries for libraries;
|
---|
1519 | instead, call once for each library member that is being loaded.
|
---|
1520 |
|
---|
1521 | FUNCTION receives two arguments: the entry, and ARG. It must be a
|
---|
1522 | function returning unsigned long (though this can probably be fudged). */
|
---|
1523 |
|
---|
1524 | unsigned long
|
---|
1525 | check_each_file (function, arg)
|
---|
1526 | register unsigned long (*function)();
|
---|
1527 | register int arg;
|
---|
1528 | {
|
---|
1529 | register int i;
|
---|
1530 | register unsigned long return_val;
|
---|
1531 |
|
---|
1532 | for (i = 0; i < number_of_files; i++)
|
---|
1533 | {
|
---|
1534 | register struct file_entry *entry = &file_table[i];
|
---|
1535 | if (entry->library_flag)
|
---|
1536 | {
|
---|
1537 | register struct file_entry *subentry = entry->subfiles;
|
---|
1538 | for (; subentry; subentry = subentry->chain)
|
---|
1539 | if ((return_val = (*function) (subentry, arg)))
|
---|
1540 | return return_val;
|
---|
1541 | }
|
---|
1542 | else
|
---|
1543 | if ((return_val = (*function) (entry, arg)))
|
---|
1544 | return return_val;
|
---|
1545 | }
|
---|
1546 | return 0;
|
---|
1547 | }
|
---|
1548 |
|
---|
1549 | /* Like `each_file' but ignore files that were just for symbol definitions. */
|
---|
1550 |
|
---|
1551 | static void
|
---|
1552 | each_full_file (function, arg)
|
---|
1553 | register void (*function)();
|
---|
1554 | register int arg;
|
---|
1555 | {
|
---|
1556 | register int i;
|
---|
1557 |
|
---|
1558 | for (i = 0; i < number_of_files; i++)
|
---|
1559 | {
|
---|
1560 | register struct file_entry *entry = &file_table[i];
|
---|
1561 | if (entry->just_syms_flag)
|
---|
1562 | continue;
|
---|
1563 | if (entry->library_flag)
|
---|
1564 | {
|
---|
1565 | register struct file_entry *subentry = entry->subfiles;
|
---|
1566 | for (; subentry; subentry = subentry->chain)
|
---|
1567 | (*function) (subentry, arg);
|
---|
1568 | }
|
---|
1569 | else
|
---|
1570 | (*function) (entry, arg);
|
---|
1571 | }
|
---|
1572 | }
|
---|
1573 |
|
---|
1574 | /* Close the input file that is now open. */
|
---|
1575 |
|
---|
1576 | static void
|
---|
1577 | file_close ()
|
---|
1578 | {
|
---|
1579 | close (input_desc);
|
---|
1580 | input_desc = 0;
|
---|
1581 | input_file = 0;
|
---|
1582 | }
|
---|
1583 |
|
---|
1584 | /* Open the input file specified by 'entry', and return a descriptor.
|
---|
1585 | The open file is remembered; if the same file is opened twice in a row,
|
---|
1586 | a new open is not actually done. */
|
---|
1587 |
|
---|
1588 | static int
|
---|
1589 | file_open (entry)
|
---|
1590 | register struct file_entry *entry;
|
---|
1591 | {
|
---|
1592 | register int desc = -1;
|
---|
1593 |
|
---|
1594 | if (entry->superfile)
|
---|
1595 | return file_open (entry->superfile);
|
---|
1596 |
|
---|
1597 | if (entry == input_file)
|
---|
1598 | return input_desc;
|
---|
1599 |
|
---|
1600 | if (input_file) file_close ();
|
---|
1601 |
|
---|
1602 | if (entry->search_dirs_flag && n_search_dirs)
|
---|
1603 | {
|
---|
1604 | /* !we're searching for libraries here! */
|
---|
1605 | static const char *dynamic_dll_suffs[] = { "_dll.a", ".a", ".dll", "_s.a", NULL };
|
---|
1606 | static const char *dynamic_suffs[] = { "_dll.a", ".a", "_s.a", NULL };
|
---|
1607 | static const char *static_suffs[] = { "_s.a", ".a", NULL };
|
---|
1608 | const char **suffs = entry->dynamic ? opt_dll_search ? dynamic_dll_suffs : dynamic_suffs : static_suffs;
|
---|
1609 | int lenname = strlen (entry->filename);
|
---|
1610 | int i;
|
---|
1611 |
|
---|
1612 | for (i = 0; i < n_search_dirs; i++)
|
---|
1613 | {
|
---|
1614 | int lendir = strlen (search_dirs[i]);
|
---|
1615 | register char *string = (char *) xmalloc (lendir + lenname + 4 + 6 + 1);
|
---|
1616 | int j;
|
---|
1617 |
|
---|
1618 | memcpy (string, search_dirs[i], lendir);
|
---|
1619 | string[lendir++] = '/';
|
---|
1620 | for (j = 0; suffs[j]; j++)
|
---|
1621 | {
|
---|
1622 | static const char *prefixes[] = { "lib", ""};
|
---|
1623 | int k;
|
---|
1624 | for (k = 0; k < sizeof(prefixes) / sizeof(prefixes[0]); k++)
|
---|
1625 | {
|
---|
1626 | int len = strlen (prefixes[k]);
|
---|
1627 | memcpy (string + lendir, prefixes[k], len);
|
---|
1628 | len += lendir;
|
---|
1629 | memcpy (string + len, entry->filename, lenname);
|
---|
1630 | len += lenname;
|
---|
1631 | strcpy (string + len, suffs[j]);
|
---|
1632 |
|
---|
1633 | desc = open (string, O_RDONLY|O_BINARY, 0);
|
---|
1634 | if (desc > 0)
|
---|
1635 | {
|
---|
1636 | /* convert? */
|
---|
1637 | if (check_lx_dll (desc))
|
---|
1638 | {
|
---|
1639 | string = lx_to_aout (string);
|
---|
1640 | if (!string || (desc = open (string, O_RDONLY|O_BINARY, 0)) < 0)
|
---|
1641 | perror_file (entry);
|
---|
1642 | }
|
---|
1643 | entry->filename = string;
|
---|
1644 | entry->search_dirs_flag = 0;
|
---|
1645 | input_file = entry;
|
---|
1646 | input_desc = desc;
|
---|
1647 | return desc;
|
---|
1648 | }
|
---|
1649 | } /* prefix loop */
|
---|
1650 | } /* suffix loop */
|
---|
1651 | free (string);
|
---|
1652 | } /* dir loop */
|
---|
1653 | }
|
---|
1654 | else
|
---|
1655 | desc = open (entry->filename, O_RDONLY|O_BINARY, 0);
|
---|
1656 |
|
---|
1657 | if (desc > 0)
|
---|
1658 | {
|
---|
1659 | input_file = entry;
|
---|
1660 | input_desc = desc;
|
---|
1661 | return desc;
|
---|
1662 | }
|
---|
1663 |
|
---|
1664 | perror_file (entry);
|
---|
1665 | /* NOTREACHED */
|
---|
1666 | return -1;
|
---|
1667 | }
|
---|
1668 |
|
---|
1669 | /* Print the filename of ENTRY on OUTFILE (a stdio stream),
|
---|
1670 | and then a newline. */
|
---|
1671 |
|
---|
1672 | void
|
---|
1673 | prline_file_name (entry, outfile)
|
---|
1674 | struct file_entry *entry;
|
---|
1675 | FILE *outfile;
|
---|
1676 | {
|
---|
1677 | print_file_name (entry, outfile);
|
---|
1678 | fprintf (outfile, "\n");
|
---|
1679 | }
|
---|
1680 |
|
---|
1681 | /* Print the filename of ENTRY on OUTFILE (a stdio stream). */
|
---|
1682 |
|
---|
1683 | void
|
---|
1684 | print_file_name (entry, outfile)
|
---|
1685 | struct file_entry *entry;
|
---|
1686 | FILE *outfile;
|
---|
1687 | {
|
---|
1688 | if (entry->superfile)
|
---|
1689 | {
|
---|
1690 | print_file_name (entry->superfile, outfile);
|
---|
1691 | fprintf (outfile, "(%s)", entry->filename);
|
---|
1692 | }
|
---|
1693 | else
|
---|
1694 | fprintf (outfile, "%s", entry->filename);
|
---|
1695 | }
|
---|
1696 |
|
---|
1697 | /* Return the filename of entry as a string (malloc'd for the purpose) */
|
---|
1698 |
|
---|
1699 | char *
|
---|
1700 | get_file_name (entry)
|
---|
1701 | struct file_entry *entry;
|
---|
1702 | {
|
---|
1703 | char *result, *supfile;
|
---|
1704 | if (entry->superfile)
|
---|
1705 | {
|
---|
1706 | supfile = get_file_name (entry->superfile);
|
---|
1707 | result = (char *) xmalloc (strlen (supfile)
|
---|
1708 | + strlen (entry->filename) + 3);
|
---|
1709 | sprintf (result, "%s(%s)", supfile, entry->filename);
|
---|
1710 | free (supfile);
|
---|
1711 | }
|
---|
1712 | else
|
---|
1713 | {
|
---|
1714 | result = (char *) xmalloc (strlen (entry->filename) + 1);
|
---|
1715 | strcpy (result, entry->filename);
|
---|
1716 | }
|
---|
1717 | return result;
|
---|
1718 | }
|
---|
1719 | |
---|
1720 |
|
---|
1721 | /* Medium-level input routines for rel files. */
|
---|
1722 |
|
---|
1723 | /* Determine whether the given ENTRY is an archive, a BSD a.out file,
|
---|
1724 | a Mach-O file, or whatever. DESC is the descriptor on which the
|
---|
1725 | file is open. */
|
---|
1726 | void
|
---|
1727 | deduce_file_type(desc, entry)
|
---|
1728 | int desc;
|
---|
1729 | struct file_entry *entry;
|
---|
1730 | {
|
---|
1731 | int len;
|
---|
1732 |
|
---|
1733 | {
|
---|
1734 | char magic[SARMAG];
|
---|
1735 |
|
---|
1736 | lseek (desc, entry->starting_offset, 0);
|
---|
1737 | len = read (desc, magic, SARMAG);
|
---|
1738 | if (len == SARMAG && !strncmp(magic, ARMAG, SARMAG))
|
---|
1739 | {
|
---|
1740 | entry->file_type = IS_ARCHIVE;
|
---|
1741 | return;
|
---|
1742 | }
|
---|
1743 | }
|
---|
1744 |
|
---|
1745 | #ifdef A_OUT
|
---|
1746 | {
|
---|
1747 | struct exec hdr;
|
---|
1748 |
|
---|
1749 | lseek (desc, entry->starting_offset, 0);
|
---|
1750 | len = read (desc, (char *) &hdr, sizeof (struct exec));
|
---|
1751 | if (len == sizeof (struct exec) && !N_BADMAG (hdr))
|
---|
1752 | {
|
---|
1753 | entry->file_type = IS_A_OUT;
|
---|
1754 | return;
|
---|
1755 | }
|
---|
1756 | }
|
---|
1757 | #endif
|
---|
1758 |
|
---|
1759 | fatal_with_file ("malformed input file (not rel or archive) ", entry);
|
---|
1760 | }
|
---|
1761 |
|
---|
1762 | #ifdef A_OUT
|
---|
1763 | /* Read an a.out file's header and set up the fields of
|
---|
1764 | the ENTRY accordingly. DESC is the descriptor on which
|
---|
1765 | the file is open. */
|
---|
1766 | void
|
---|
1767 | read_a_out_header (desc, entry)
|
---|
1768 | int desc;
|
---|
1769 | struct file_entry *entry;
|
---|
1770 | {
|
---|
1771 | struct exec hdr;
|
---|
1772 | struct stat st;
|
---|
1773 |
|
---|
1774 | lseek (desc, entry->starting_offset, 0);
|
---|
1775 | read (desc, (char *) &hdr, sizeof (struct exec));
|
---|
1776 |
|
---|
1777 | #ifdef READ_HEADER_HOOK
|
---|
1778 | READ_HEADER_HOOK(hdr.a_machtype);
|
---|
1779 | #endif
|
---|
1780 |
|
---|
1781 | if (entry->just_syms_flag)
|
---|
1782 | entry->orig_text_address = N_TXTADDR(hdr);
|
---|
1783 | else
|
---|
1784 | entry->orig_text_address = 0;
|
---|
1785 | entry->text_size = hdr.a_text;
|
---|
1786 | entry->text_offset = N_TXTOFF(hdr);
|
---|
1787 |
|
---|
1788 | entry->text_reloc_size = hdr.a_trsize;
|
---|
1789 | #ifdef N_TRELOFF
|
---|
1790 | entry->text_reloc_offset = N_TRELOFF(hdr);
|
---|
1791 | #else
|
---|
1792 | #ifdef N_DATOFF
|
---|
1793 | entry->text_reloc_offset = N_DATOFF(hdr) + hdr.a_data;
|
---|
1794 | #else
|
---|
1795 | entry->text_reloc_offset = N_TXTOFF(hdr) + hdr.a_text + hdr.a_data;
|
---|
1796 | #endif
|
---|
1797 | #endif
|
---|
1798 |
|
---|
1799 | if (entry->just_syms_flag)
|
---|
1800 | entry->orig_data_address = N_DATADDR(hdr);
|
---|
1801 | else
|
---|
1802 | entry->orig_data_address = entry->text_size;
|
---|
1803 | entry->data_size = hdr.a_data;
|
---|
1804 | #ifdef N_DATOFF
|
---|
1805 | entry->data_offset = N_DATOFF(hdr);
|
---|
1806 | #else
|
---|
1807 | entry->data_offset = N_TXTOFF(hdr) + hdr.a_text;
|
---|
1808 | #endif
|
---|
1809 |
|
---|
1810 | entry->data_reloc_size = hdr.a_drsize;
|
---|
1811 | #ifdef N_DRELOFF
|
---|
1812 | entry->data_reloc_offset = N_DRELOFF(hdr);
|
---|
1813 | #else
|
---|
1814 | entry->data_reloc_offset = entry->text_reloc_offset + entry->text_reloc_size;
|
---|
1815 | #endif
|
---|
1816 |
|
---|
1817 | #ifdef N_BSSADDR
|
---|
1818 | if (entry->just_syms_flag)
|
---|
1819 | entry->orig_bss_address = N_BSSADDR(hdr);
|
---|
1820 | else
|
---|
1821 | #endif
|
---|
1822 | entry->orig_bss_address = entry->orig_data_address + entry->data_size;
|
---|
1823 | entry->bss_size = hdr.a_bss;
|
---|
1824 |
|
---|
1825 | entry->syms_size = hdr.a_syms;
|
---|
1826 | entry->syms_offset = N_SYMOFF(hdr);
|
---|
1827 | entry->strs_offset = N_STROFF(hdr);
|
---|
1828 | lseek(desc, entry->starting_offset + entry->strs_offset, 0);
|
---|
1829 | if (entry->syms_size &&
|
---|
1830 | read(desc, (char *) &entry->strs_size, sizeof (unsigned long int))
|
---|
1831 | != sizeof (unsigned long int))
|
---|
1832 | fatal_with_file ("failure reading string table size of ", entry);
|
---|
1833 |
|
---|
1834 | if (!entry->superfile)
|
---|
1835 | {
|
---|
1836 | fstat(desc, &st);
|
---|
1837 | if (st.st_size > entry->strs_offset + entry->strs_size)
|
---|
1838 | {
|
---|
1839 | entry->symseg_size = st.st_size - (entry->strs_offset + entry->strs_size);
|
---|
1840 | entry->symseg_offset = entry->strs_offset + entry->strs_size;
|
---|
1841 | }
|
---|
1842 | }
|
---|
1843 | else
|
---|
1844 | if (entry->total_size > entry->strs_offset + entry->strs_size)
|
---|
1845 | {
|
---|
1846 | entry->symseg_size = entry->total_size - (entry->strs_offset + entry->strs_size);
|
---|
1847 | entry->symseg_offset = entry->strs_offset + entry->strs_size;
|
---|
1848 | }
|
---|
1849 | }
|
---|
1850 | #endif
|
---|
1851 |
|
---|
1852 | /* Read a file's header info into the proper place in the file_entry.
|
---|
1853 | DESC is the descriptor on which the file is open.
|
---|
1854 | ENTRY is the file's entry.
|
---|
1855 | Switch in the file_type to determine the appropriate actual
|
---|
1856 | header reading routine to call. */
|
---|
1857 |
|
---|
1858 | void
|
---|
1859 | read_header (desc, entry)
|
---|
1860 | int desc;
|
---|
1861 | register struct file_entry *entry;
|
---|
1862 | {
|
---|
1863 | if (!entry->file_type)
|
---|
1864 | deduce_file_type (desc, entry);
|
---|
1865 |
|
---|
1866 | switch (entry->file_type)
|
---|
1867 | {
|
---|
1868 | case IS_ARCHIVE:
|
---|
1869 | default:
|
---|
1870 | /* Should never happen. */
|
---|
1871 | abort ();
|
---|
1872 |
|
---|
1873 | #ifdef A_OUT
|
---|
1874 | case IS_A_OUT:
|
---|
1875 | read_a_out_header (desc, entry);
|
---|
1876 | break;
|
---|
1877 | #endif
|
---|
1878 | }
|
---|
1879 |
|
---|
1880 | entry->header_read_flag = 1;
|
---|
1881 | }
|
---|
1882 |
|
---|
1883 | /* Read the symbols of file ENTRY into core.
|
---|
1884 | Assume it is already open, on descriptor DESC. */
|
---|
1885 |
|
---|
1886 | void
|
---|
1887 | read_entry_symbols (desc, entry)
|
---|
1888 | struct file_entry *entry;
|
---|
1889 | int desc;
|
---|
1890 | {
|
---|
1891 | if (!entry->header_read_flag)
|
---|
1892 | read_header (desc, entry);
|
---|
1893 |
|
---|
1894 | entry->symbols = (struct nlist *) xmalloc (entry->syms_size);
|
---|
1895 |
|
---|
1896 | lseek (desc, entry->syms_offset + entry->starting_offset, 0);
|
---|
1897 | if (entry->syms_size != read (desc, entry->symbols, entry->syms_size))
|
---|
1898 | fatal_with_file ("premature end of file in symbols of ", entry);
|
---|
1899 | }
|
---|
1900 |
|
---|
1901 | /* Read the string table of file ENTRY into core.
|
---|
1902 | Assume it is already open, on descriptor DESC. */
|
---|
1903 |
|
---|
1904 | void
|
---|
1905 | read_entry_strings (desc, entry)
|
---|
1906 | int desc;
|
---|
1907 | struct file_entry *entry;
|
---|
1908 | {
|
---|
1909 | if (!entry->header_read_flag)
|
---|
1910 | read_header (desc, entry);
|
---|
1911 |
|
---|
1912 | lseek (desc, entry->strs_offset + entry->starting_offset, 0);
|
---|
1913 | if (entry->strs_size != read (desc, entry->strings, entry->strs_size))
|
---|
1914 | fatal_with_file ("premature end of file in strings of ", entry);
|
---|
1915 | }
|
---|
1916 | |
---|
1917 |
|
---|
1918 | /* Read in the symbols of all input files. */
|
---|
1919 |
|
---|
1920 | void enter_file_symbols (struct file_entry *entry);
|
---|
1921 | void enter_global_ref (register struct nlist *nlist_p, char *name, struct file_entry *entry);
|
---|
1922 | void search_library (int desc, struct file_entry *entry);
|
---|
1923 |
|
---|
1924 | void
|
---|
1925 | load_symbols (void)
|
---|
1926 | {
|
---|
1927 | register int i;
|
---|
1928 |
|
---|
1929 | if (trace_files) fprintf (stderr, "Loading symbols:\n\n");
|
---|
1930 |
|
---|
1931 | for (i = 0; i < number_of_files; i++)
|
---|
1932 | {
|
---|
1933 | register struct file_entry *entry = &file_table[i];
|
---|
1934 | read_file_symbols (entry);
|
---|
1935 | }
|
---|
1936 |
|
---|
1937 | if (trace_files) fprintf (stderr, "\n");
|
---|
1938 | }
|
---|
1939 |
|
---|
1940 | /* If ENTRY is a rel file, read its symbol and string sections into core.
|
---|
1941 | If it is a library, search it and load the appropriate members
|
---|
1942 | (which means calling this function recursively on those members). */
|
---|
1943 |
|
---|
1944 | void
|
---|
1945 | read_file_symbols (entry)
|
---|
1946 | register struct file_entry *entry;
|
---|
1947 | {
|
---|
1948 | register int desc;
|
---|
1949 |
|
---|
1950 | desc = file_open (entry);
|
---|
1951 |
|
---|
1952 | if (!entry->file_type)
|
---|
1953 | deduce_file_type (desc, entry);
|
---|
1954 |
|
---|
1955 | if (entry->file_type == IS_ARCHIVE)
|
---|
1956 | {
|
---|
1957 | entry->library_flag = 1;
|
---|
1958 | search_library (desc, entry);
|
---|
1959 | }
|
---|
1960 | else
|
---|
1961 | {
|
---|
1962 | read_entry_symbols (desc, entry);
|
---|
1963 | entry->strings = (char *) ALLOCA (entry->strs_size);
|
---|
1964 | read_entry_strings (desc, entry);
|
---|
1965 | enter_file_symbols (entry);
|
---|
1966 | FREEA (entry->strings);
|
---|
1967 | }
|
---|
1968 |
|
---|
1969 | file_close ();
|
---|
1970 | }
|
---|
1971 | |
---|
1972 |
|
---|
1973 | /* Enter the external symbol defs and refs of ENTRY in the hash table. */
|
---|
1974 |
|
---|
1975 | void
|
---|
1976 | enter_file_symbols (entry)
|
---|
1977 | struct file_entry *entry;
|
---|
1978 | {
|
---|
1979 | register struct nlist
|
---|
1980 | *p,
|
---|
1981 | *end = entry->symbols + entry->syms_size / sizeof (struct nlist);
|
---|
1982 |
|
---|
1983 | if (trace_files) prline_file_name (entry, stderr);
|
---|
1984 |
|
---|
1985 | for (p = entry->symbols; p < end; p++)
|
---|
1986 | {
|
---|
1987 | if (p->n_type == (N_SETV | N_EXT)) continue;
|
---|
1988 | if (p->n_type == (N_IMP1 | N_EXT))
|
---|
1989 | reloc_flag = 1;
|
---|
1990 | if (set_element_prefixes
|
---|
1991 | && set_element_prefixed_p (p->n_un.n_strx + entry->strings))
|
---|
1992 | p->n_type += (N_SETA - N_ABS);
|
---|
1993 |
|
---|
1994 | if (SET_ELEMENT_P (p->n_type))
|
---|
1995 | {
|
---|
1996 | set_symbol_count++;
|
---|
1997 | if (output_style != OUTPUT_RELOCATABLE)
|
---|
1998 | enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);
|
---|
1999 | }
|
---|
2000 | else if (p->n_type == N_WARNING)
|
---|
2001 | {
|
---|
2002 | char *name = p->n_un.n_strx + entry->strings;
|
---|
2003 |
|
---|
2004 | /* Grab the next entry. */
|
---|
2005 | p++;
|
---|
2006 | if (p->n_type != (N_UNDF | N_EXT))
|
---|
2007 | {
|
---|
2008 | fprintf (stderr, "%s: Warning symbol found in %s without external reference following.\n",
|
---|
2009 | progname, entry->filename);
|
---|
2010 | make_executable = 0;
|
---|
2011 | p--; /* Process normally. */
|
---|
2012 | }
|
---|
2013 | else
|
---|
2014 | {
|
---|
2015 | symbol *sp;
|
---|
2016 | char *sname = p->n_un.n_strx + entry->strings;
|
---|
2017 | /* Deal with the warning symbol. */
|
---|
2018 | enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);
|
---|
2019 | sp = getsym (sname);
|
---|
2020 | sp->warning = (char *) xmalloc (strlen(name) + 1);
|
---|
2021 | strcpy (sp->warning, name);
|
---|
2022 | warning_count++;
|
---|
2023 | }
|
---|
2024 | }
|
---|
2025 | else if (WEAK_SYMBOL (p->n_type))
|
---|
2026 | {
|
---|
2027 | /* Enter the symbol into the symbol hash table only if it
|
---|
2028 | has not already been defined */
|
---|
2029 | symbol *s = getsym_soft (p->n_un.n_strx + entry->strings);
|
---|
2030 | if (!s || !s->defined)
|
---|
2031 | enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);
|
---|
2032 | else if (s) /* hack! */
|
---|
2033 | p->n_un.n_name = (char*)s;
|
---|
2034 | #ifdef DEBUG
|
---|
2035 | else fprintf(stderr, "dbg-warning: %s - sym %d: '%s' no such symbol...\n",
|
---|
2036 | entry->filename,
|
---|
2037 | p - entry->symbols,
|
---|
2038 | p->n_un.n_strx + entry->strings);
|
---|
2039 | #endif
|
---|
2040 | }
|
---|
2041 | else if (p->n_type & N_EXT)
|
---|
2042 | enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);
|
---|
2043 | else if (p->n_un.n_strx && !(p->n_type & (N_STAB | N_EXT)))
|
---|
2044 | {
|
---|
2045 | if ((p->n_un.n_strx + entry->strings)[0] != LPREFIX)
|
---|
2046 | non_L_local_sym_count++;
|
---|
2047 | local_sym_count++;
|
---|
2048 | }
|
---|
2049 | else debugger_sym_count++;
|
---|
2050 | #ifdef DEBUG_BIRD
|
---|
2051 | fprintf(stderr, "dbg: %s sym #%3d: un=%08lx typ=%02x\n",
|
---|
2052 | entry->filename,
|
---|
2053 | p - entry->symbols,
|
---|
2054 | p->n_un.n_strx,
|
---|
2055 | p->n_type);
|
---|
2056 | #endif
|
---|
2057 | }
|
---|
2058 |
|
---|
2059 | /* Count one for the local symbol that we generate,
|
---|
2060 | whose name is the file's name (usually) and whose address
|
---|
2061 | is the start of the file's text. */
|
---|
2062 |
|
---|
2063 | local_sym_count++;
|
---|
2064 | non_L_local_sym_count++;
|
---|
2065 | }
|
---|
2066 |
|
---|
2067 | /* Enter one global symbol in the hash table.
|
---|
2068 | NLIST_P points to the `struct nlist' read from the file
|
---|
2069 | that describes the global symbol. NAME is the symbol's name.
|
---|
2070 | ENTRY is the file entry for the file the symbol comes from.
|
---|
2071 |
|
---|
2072 | The `struct nlist' is modified by placing it on a chain of
|
---|
2073 | all such structs that refer to the same global symbol.
|
---|
2074 | This chain starts in the `refs' field of the symbol table entry
|
---|
2075 | and is chained through the `n_name'. */
|
---|
2076 |
|
---|
2077 | void
|
---|
2078 | enter_global_ref (nlist_p, name, entry)
|
---|
2079 | register struct nlist *nlist_p;
|
---|
2080 | char *name;
|
---|
2081 | struct file_entry *entry;
|
---|
2082 | {
|
---|
2083 | register symbol *sp = getsym (name);
|
---|
2084 | register int type = nlist_p->n_type;
|
---|
2085 | const int realtype = type;
|
---|
2086 | int oldref = sp->referenced;
|
---|
2087 | int olddef = sp->defined;
|
---|
2088 |
|
---|
2089 | nlist_p->n_un.n_name = (char *) sp->refs;
|
---|
2090 | sp->refs = nlist_p;
|
---|
2091 |
|
---|
2092 | sp->referenced = 1;
|
---|
2093 |
|
---|
2094 | if (WEAK_SYMBOL (type))
|
---|
2095 | {
|
---|
2096 | sp->weak = type;
|
---|
2097 | /* Switch symbol type so that it can be processed like regular symbols */
|
---|
2098 | type = nlist_p->n_type =
|
---|
2099 | (type == N_WEAKU) ? N_UNDF | N_EXT :
|
---|
2100 | (type == N_WEAKA) ? N_ABS | N_EXT :
|
---|
2101 | (type == N_WEAKT) ? N_TEXT | N_EXT :
|
---|
2102 | (type == N_WEAKD) ? N_DATA | N_EXT :
|
---|
2103 | /*(type == N_WEAKB)*/ N_BSS | N_EXT;
|
---|
2104 | }
|
---|
2105 |
|
---|
2106 | if (type != (N_UNDF | N_EXT) || nlist_p->n_value)
|
---|
2107 | {
|
---|
2108 | if (!sp->defined || sp->defined == (N_UNDF | N_EXT))
|
---|
2109 | sp->defined = type;
|
---|
2110 |
|
---|
2111 | if (oldref && !olddef)
|
---|
2112 | /* It used to be undefined and we're defining it. */
|
---|
2113 | undefined_global_sym_count--;
|
---|
2114 |
|
---|
2115 | if (!olddef && type == (N_UNDF | N_EXT) && nlist_p->n_value)
|
---|
2116 | {
|
---|
2117 | /* First definition and it's common. */
|
---|
2118 | common_defined_global_count++;
|
---|
2119 | sp->max_common_size = nlist_p->n_value;
|
---|
2120 | }
|
---|
2121 | else if (olddef && sp->max_common_size && type != (N_UNDF | N_EXT))
|
---|
2122 | {
|
---|
2123 | /* It used to be common and we're defining it as
|
---|
2124 | something else. */
|
---|
2125 | common_defined_global_count--;
|
---|
2126 | sp->max_common_size = 0;
|
---|
2127 |
|
---|
2128 | fprintf (stderr, "%s: symbol `%s' defined more than once in ",
|
---|
2129 | progname, name);
|
---|
2130 | print_file_name (entry, stderr);
|
---|
2131 | fprintf (stderr, "\n");
|
---|
2132 | exit (1);
|
---|
2133 | }
|
---|
2134 | else if (olddef && sp->max_common_size && type == (N_UNDF | N_EXT)
|
---|
2135 | && sp->max_common_size < nlist_p->n_value)
|
---|
2136 | /* It used to be common and this is a new common entry to
|
---|
2137 | which we need to pay attention. */
|
---|
2138 | sp->max_common_size = nlist_p->n_value;
|
---|
2139 |
|
---|
2140 | /* Are we defining it as a set element? */
|
---|
2141 | if (SET_ELEMENT_P (type)
|
---|
2142 | && (!olddef || (olddef && sp->max_common_size)))
|
---|
2143 | set_vector_count++;
|
---|
2144 | /* As an indirection? */
|
---|
2145 | else if (type == (N_INDR | N_EXT))
|
---|
2146 | {
|
---|
2147 | /* Indirect symbols value should be modified to point
|
---|
2148 | a symbol being equivalenced to. */
|
---|
2149 | nlist_p->n_value
|
---|
2150 | = (unsigned int) getsym ((nlist_p + 1)->n_un.n_strx
|
---|
2151 | + entry->strings);
|
---|
2152 | if ((symbol *) nlist_p->n_value == sp)
|
---|
2153 | {
|
---|
2154 | /* Somebody redefined a symbol to be itself. */
|
---|
2155 | fprintf (stderr, "%s: Symbol %s indirected to itself.\n",
|
---|
2156 | entry->filename, name);
|
---|
2157 | /* Rewrite this symbol as being a global text symbol
|
---|
2158 | with value 0. */
|
---|
2159 | nlist_p->n_type = sp->defined = N_TEXT | N_EXT;
|
---|
2160 | nlist_p->n_value = 0;
|
---|
2161 | /* Don't make the output executable. */
|
---|
2162 | make_executable = 0;
|
---|
2163 | }
|
---|
2164 | else
|
---|
2165 | global_indirect_count++;
|
---|
2166 | }
|
---|
2167 | }
|
---|
2168 | else
|
---|
2169 | if (!oldref)
|
---|
2170 | undefined_global_sym_count++;
|
---|
2171 |
|
---|
2172 | if (sp == end_symbol && entry->just_syms_flag && !T_flag_specified)
|
---|
2173 | text_start = nlist_p->n_value;
|
---|
2174 |
|
---|
2175 | #ifdef DEBUG_BIRD
|
---|
2176 | sp->trace = 1;
|
---|
2177 | #endif
|
---|
2178 | if (sp->trace)
|
---|
2179 | {
|
---|
2180 | register char *reftype;
|
---|
2181 | int free_reftype = 0;
|
---|
2182 | switch (realtype & ~N_EXT)
|
---|
2183 | {
|
---|
2184 | case N_UNDF:
|
---|
2185 | if (nlist_p->n_value)
|
---|
2186 | reftype = "defined as common";
|
---|
2187 | else reftype = "referenced";
|
---|
2188 | break;
|
---|
2189 |
|
---|
2190 | case N_ABS:
|
---|
2191 | reftype = "defined as absolute";
|
---|
2192 | break;
|
---|
2193 |
|
---|
2194 | case N_TEXT:
|
---|
2195 | reftype = "defined in text section";
|
---|
2196 | break;
|
---|
2197 |
|
---|
2198 | case N_DATA:
|
---|
2199 | reftype = "defined in data section";
|
---|
2200 | break;
|
---|
2201 |
|
---|
2202 | case N_BSS:
|
---|
2203 | reftype = "defined in BSS section";
|
---|
2204 | break;
|
---|
2205 |
|
---|
2206 | case N_SETT:
|
---|
2207 | reftype = "is a text set element";
|
---|
2208 | break;
|
---|
2209 |
|
---|
2210 | case N_SETD:
|
---|
2211 | reftype = "is a data set element";
|
---|
2212 | break;
|
---|
2213 |
|
---|
2214 | case N_SETB:
|
---|
2215 | reftype = "is a BSS set element";
|
---|
2216 | break;
|
---|
2217 |
|
---|
2218 | case N_SETA:
|
---|
2219 | reftype = "is an absolute set element";
|
---|
2220 | break;
|
---|
2221 |
|
---|
2222 | case N_SETV:
|
---|
2223 | reftype = "defined in data section as vector";
|
---|
2224 | break;
|
---|
2225 |
|
---|
2226 | case N_INDR:
|
---|
2227 | reftype = (char *) ALLOCA (23 + strlen (((symbol *) nlist_p->n_value)->name));
|
---|
2228 | sprintf (reftype, "defined equivalent to %s",
|
---|
2229 | ((symbol *) nlist_p->n_value)->name);
|
---|
2230 | free_reftype = 1;
|
---|
2231 | break;
|
---|
2232 |
|
---|
2233 | case N_IMP1:
|
---|
2234 | reftype = "imported";
|
---|
2235 | break;
|
---|
2236 |
|
---|
2237 | case N_WEAKU & ~N_EXT:
|
---|
2238 | reftype = "weak";
|
---|
2239 | break;
|
---|
2240 |
|
---|
2241 | case N_WEAKT & ~N_EXT:
|
---|
2242 | reftype = "weak text";
|
---|
2243 | break;
|
---|
2244 |
|
---|
2245 | case N_WEAKD & ~N_EXT:
|
---|
2246 | reftype = "weak data";
|
---|
2247 | break;
|
---|
2248 |
|
---|
2249 | default:
|
---|
2250 | reftype = "I don't know this type";
|
---|
2251 | break;
|
---|
2252 | }
|
---|
2253 |
|
---|
2254 |
|
---|
2255 | fprintf (stderr, "symbol in ");
|
---|
2256 | print_file_name (entry, stderr);
|
---|
2257 | fprintf (stderr, ": %3d %s %s\n",
|
---|
2258 | nlist_p - entry->symbols, sp->name, reftype);
|
---|
2259 | if (free_reftype)
|
---|
2260 | FREEA (reftype);
|
---|
2261 | }
|
---|
2262 | }
|
---|
2263 |
|
---|
2264 | /* This return 0 if the given file entry's symbol table does *not*
|
---|
2265 | contain the nlist point entry, and it returns the files entry
|
---|
2266 | pointer (cast to unsigned long) if it does. */
|
---|
2267 |
|
---|
2268 | unsigned long
|
---|
2269 | contains_symbol (entry, n_ptr)
|
---|
2270 | struct file_entry *entry;
|
---|
2271 | register struct nlist *n_ptr;
|
---|
2272 | {
|
---|
2273 | if (n_ptr >= entry->symbols &&
|
---|
2274 | n_ptr < (entry->symbols
|
---|
2275 | + (entry->syms_size / sizeof (struct nlist))))
|
---|
2276 | return (unsigned long) entry;
|
---|
2277 | return 0;
|
---|
2278 | }
|
---|
2279 |
|
---|
2280 | |
---|
2281 |
|
---|
2282 | /* Searching libraries */
|
---|
2283 |
|
---|
2284 | struct file_entry * decode_library_subfile (int desc, struct file_entry *library_entry, int subfile_offset, int *length_loc);
|
---|
2285 | void symdef_library (int desc, struct file_entry *entry, int member_length);
|
---|
2286 | void linear_library (int desc, struct file_entry *entry);
|
---|
2287 |
|
---|
2288 | /* Search the library ENTRY, already open on descriptor DESC.
|
---|
2289 | This means deciding which library members to load,
|
---|
2290 | making a chain of `struct file_entry' for those members,
|
---|
2291 | and entering their global symbols in the hash table. */
|
---|
2292 |
|
---|
2293 | void
|
---|
2294 | search_library (desc, entry)
|
---|
2295 | int desc;
|
---|
2296 | struct file_entry *entry;
|
---|
2297 | {
|
---|
2298 | int member_length;
|
---|
2299 | register char *name;
|
---|
2300 | register struct file_entry *subentry;
|
---|
2301 |
|
---|
2302 | if (!undefined_global_sym_count) return;
|
---|
2303 |
|
---|
2304 | /* Examine its first member, which starts SARMAG bytes in. */
|
---|
2305 | subentry = decode_library_subfile (desc, entry, SARMAG, &member_length);
|
---|
2306 | if (!subentry) return;
|
---|
2307 |
|
---|
2308 | name = subentry->filename;
|
---|
2309 | free (subentry);
|
---|
2310 |
|
---|
2311 | /* Search via __.SYMDEF if that exists, else linearly. */
|
---|
2312 |
|
---|
2313 | if (!strcmp (name, "__.SYMDEF"))
|
---|
2314 | symdef_library (desc, entry, member_length);
|
---|
2315 | else
|
---|
2316 | linear_library (desc, entry);
|
---|
2317 | }
|
---|
2318 |
|
---|
2319 | /* Construct and return a file_entry for a library member.
|
---|
2320 | The library's file_entry is library_entry, and the library is open on DESC.
|
---|
2321 | SUBFILE_OFFSET is the byte index in the library of this member's header.
|
---|
2322 | We store the length of the member into *LENGTH_LOC. */
|
---|
2323 |
|
---|
2324 | struct file_entry *
|
---|
2325 | decode_library_subfile (desc, library_entry, subfile_offset, length_loc)
|
---|
2326 | int desc;
|
---|
2327 | struct file_entry *library_entry;
|
---|
2328 | int subfile_offset;
|
---|
2329 | int *length_loc;
|
---|
2330 | {
|
---|
2331 | int bytes_read;
|
---|
2332 | register int namelen;
|
---|
2333 | int member_length;
|
---|
2334 | register char *name;
|
---|
2335 | struct ar_hdr hdr1;
|
---|
2336 | register struct file_entry *subentry;
|
---|
2337 |
|
---|
2338 | lseek (desc, subfile_offset, 0);
|
---|
2339 |
|
---|
2340 | bytes_read = read (desc, &hdr1, sizeof hdr1);
|
---|
2341 | if (!bytes_read)
|
---|
2342 | return 0; /* end of archive */
|
---|
2343 |
|
---|
2344 | if (sizeof hdr1 != bytes_read)
|
---|
2345 | fatal_with_file ("malformed library archive ", library_entry);
|
---|
2346 |
|
---|
2347 | if (sscanf (hdr1.ar_size, "%d", &member_length) != 1)
|
---|
2348 | fatal_with_file ("malformatted header of archive member in ", library_entry);
|
---|
2349 |
|
---|
2350 | subentry = (struct file_entry *) xmalloc (sizeof (struct file_entry));
|
---|
2351 | bzero (subentry, sizeof (struct file_entry));
|
---|
2352 |
|
---|
2353 | for (namelen = 0;
|
---|
2354 | namelen < sizeof hdr1.ar_name
|
---|
2355 | && hdr1.ar_name[namelen] != 0 && hdr1.ar_name[namelen] != ' '
|
---|
2356 | && hdr1.ar_name[namelen] != '/';
|
---|
2357 | namelen++);
|
---|
2358 |
|
---|
2359 | name = (char *) xmalloc (namelen+1);
|
---|
2360 | strncpy (name, hdr1.ar_name, namelen);
|
---|
2361 | name[namelen] = 0;
|
---|
2362 |
|
---|
2363 | subentry->filename = name;
|
---|
2364 | subentry->local_sym_name = name;
|
---|
2365 | subentry->symbols = 0;
|
---|
2366 | subentry->strings = 0;
|
---|
2367 | subentry->subfiles = 0;
|
---|
2368 | subentry->starting_offset = subfile_offset + sizeof hdr1;
|
---|
2369 | subentry->superfile = library_entry;
|
---|
2370 | subentry->library_flag = 0;
|
---|
2371 | subentry->header_read_flag = 0;
|
---|
2372 | subentry->just_syms_flag = 0;
|
---|
2373 | subentry->chain = 0;
|
---|
2374 | subentry->total_size = member_length;
|
---|
2375 |
|
---|
2376 | (*length_loc) = member_length;
|
---|
2377 |
|
---|
2378 | return subentry;
|
---|
2379 | }
|
---|
2380 | |
---|
2381 |
|
---|
2382 | int subfile_wanted_p (struct file_entry *);
|
---|
2383 |
|
---|
2384 | /* Search a library that has a __.SYMDEF member.
|
---|
2385 | DESC is a descriptor on which the library is open.
|
---|
2386 | The file pointer is assumed to point at the __.SYMDEF data.
|
---|
2387 | ENTRY is the library's file_entry.
|
---|
2388 | MEMBER_LENGTH is the length of the __.SYMDEF data. */
|
---|
2389 |
|
---|
2390 | void
|
---|
2391 | symdef_library (desc, entry, member_length)
|
---|
2392 | int desc;
|
---|
2393 | struct file_entry *entry;
|
---|
2394 | int member_length;
|
---|
2395 | {
|
---|
2396 | int *symdef_data = (int *) xmalloc (member_length);
|
---|
2397 | register struct symdef *symdef_base;
|
---|
2398 | char *sym_name_base;
|
---|
2399 | int number_of_symdefs;
|
---|
2400 | int length_of_strings;
|
---|
2401 | int not_finished;
|
---|
2402 | int bytes_read;
|
---|
2403 | register int i;
|
---|
2404 | struct file_entry *prev = 0;
|
---|
2405 | int prev_offset = 0;
|
---|
2406 |
|
---|
2407 | bytes_read = read (desc, symdef_data, member_length);
|
---|
2408 | if (bytes_read != member_length)
|
---|
2409 | fatal_with_file ("malformatted __.SYMDEF in ", entry);
|
---|
2410 |
|
---|
2411 | number_of_symdefs = *symdef_data / sizeof (struct symdef);
|
---|
2412 | if (number_of_symdefs < 0 ||
|
---|
2413 | number_of_symdefs * sizeof (struct symdef) + 2 * sizeof (int) > member_length)
|
---|
2414 | fatal_with_file ("malformatted __.SYMDEF in ", entry);
|
---|
2415 |
|
---|
2416 | symdef_base = (struct symdef *) (symdef_data + 1);
|
---|
2417 | length_of_strings = *(int *) (symdef_base + number_of_symdefs);
|
---|
2418 |
|
---|
2419 | if (length_of_strings < 0
|
---|
2420 | || number_of_symdefs * sizeof (struct symdef) + length_of_strings
|
---|
2421 | + 2 * sizeof (int) != member_length)
|
---|
2422 | fatal_with_file ("malformatted __.SYMDEF in ", entry);
|
---|
2423 |
|
---|
2424 | sym_name_base = sizeof (int) + (char *) (symdef_base + number_of_symdefs);
|
---|
2425 |
|
---|
2426 | /* Check all the string indexes for validity. */
|
---|
2427 |
|
---|
2428 | for (i = 0; i < number_of_symdefs; i++)
|
---|
2429 | {
|
---|
2430 | register int index = symdef_base[i].symbol_name_string_index;
|
---|
2431 | if (index < 0 || index >= length_of_strings
|
---|
2432 | || (index && *(sym_name_base + index - 1)))
|
---|
2433 | fatal_with_file ("malformatted __.SYMDEF in ", entry);
|
---|
2434 | }
|
---|
2435 |
|
---|
2436 | /* Search the symdef data for members to load.
|
---|
2437 | Do this until one whole pass finds nothing to load. */
|
---|
2438 |
|
---|
2439 | not_finished = 1;
|
---|
2440 | while (not_finished)
|
---|
2441 | {
|
---|
2442 | not_finished = 0;
|
---|
2443 |
|
---|
2444 | /* Scan all the symbols mentioned in the symdef for ones that we need.
|
---|
2445 | Load the library members that contain such symbols. */
|
---|
2446 |
|
---|
2447 | for (i = 0;
|
---|
2448 | (i < number_of_symdefs
|
---|
2449 | && (undefined_global_sym_count || common_defined_global_count));
|
---|
2450 | i++)
|
---|
2451 | if (symdef_base[i].symbol_name_string_index >= 0)
|
---|
2452 | {
|
---|
2453 | register symbol *sp;
|
---|
2454 |
|
---|
2455 | sp = getsym_soft (sym_name_base
|
---|
2456 | + symdef_base[i].symbol_name_string_index);
|
---|
2457 |
|
---|
2458 | /* If we find a symbol that appears to be needed, think carefully
|
---|
2459 | about the archive member that the symbol is in. */
|
---|
2460 |
|
---|
2461 | if (sp && ((sp->referenced && !sp->defined)
|
---|
2462 | || (sp->defined && sp->max_common_size))
|
---|
2463 | )
|
---|
2464 | {
|
---|
2465 | int junk;
|
---|
2466 | register int j;
|
---|
2467 | register int offset = symdef_base[i].library_member_offset;
|
---|
2468 | struct file_entry *subentry;
|
---|
2469 |
|
---|
2470 | /* Don't think carefully about any archive member
|
---|
2471 | more than once in a given pass. */
|
---|
2472 |
|
---|
2473 | if (prev_offset == offset)
|
---|
2474 | continue;
|
---|
2475 | prev_offset = offset;
|
---|
2476 |
|
---|
2477 | /* Read the symbol table of the archive member. */
|
---|
2478 |
|
---|
2479 | subentry = decode_library_subfile (desc, entry, offset, &junk);
|
---|
2480 | if (subentry == 0)
|
---|
2481 | fatal ("invalid offset for %s in symbol table of %s",
|
---|
2482 | sym_name_base
|
---|
2483 | + symdef_base[i].symbol_name_string_index,
|
---|
2484 | entry->filename);
|
---|
2485 | read_entry_symbols (desc, subentry);
|
---|
2486 | subentry->strings = (char *) xmalloc (subentry->strs_size);
|
---|
2487 | read_entry_strings (desc, subentry);
|
---|
2488 |
|
---|
2489 | /* Now scan the symbol table and decide whether to load. */
|
---|
2490 |
|
---|
2491 | if (!subfile_wanted_p (subentry))
|
---|
2492 | {
|
---|
2493 | free (subentry->symbols);
|
---|
2494 | free (subentry->strings);
|
---|
2495 | free (subentry);
|
---|
2496 | }
|
---|
2497 | else
|
---|
2498 | {
|
---|
2499 | /* This member is needed; load it.
|
---|
2500 | Since we are loading something on this pass,
|
---|
2501 | we must make another pass through the symdef data. */
|
---|
2502 |
|
---|
2503 | not_finished = 1;
|
---|
2504 |
|
---|
2505 | enter_file_symbols (subentry);
|
---|
2506 |
|
---|
2507 | if (prev)
|
---|
2508 | prev->chain = subentry;
|
---|
2509 | else entry->subfiles = subentry;
|
---|
2510 | prev = subentry;
|
---|
2511 |
|
---|
2512 | /* Clear out this member's symbols from the symdef data
|
---|
2513 | so that following passes won't waste time on them. */
|
---|
2514 |
|
---|
2515 | for (j = 0; j < number_of_symdefs; j++)
|
---|
2516 | {
|
---|
2517 | if (symdef_base[j].library_member_offset == offset)
|
---|
2518 | symdef_base[j].symbol_name_string_index = -1;
|
---|
2519 | }
|
---|
2520 |
|
---|
2521 | /* We'll read the strings again if we need them again. */
|
---|
2522 | free (subentry->strings);
|
---|
2523 | subentry->strings = 0;
|
---|
2524 | }
|
---|
2525 | }
|
---|
2526 | }
|
---|
2527 | }
|
---|
2528 |
|
---|
2529 | free (symdef_data);
|
---|
2530 | }
|
---|
2531 | |
---|
2532 |
|
---|
2533 |
|
---|
2534 | /* Handle a subentry for a file with no __.SYMDEF. */
|
---|
2535 |
|
---|
2536 | void
|
---|
2537 | process_subentry (desc, subentry, entry, prev_addr)
|
---|
2538 | int desc;
|
---|
2539 | register struct file_entry *subentry;
|
---|
2540 | struct file_entry **prev_addr, *entry;
|
---|
2541 | {
|
---|
2542 | read_entry_symbols (desc, subentry);
|
---|
2543 | subentry->strings = (char *) ALLOCA (subentry->strs_size);
|
---|
2544 | read_entry_strings (desc, subentry);
|
---|
2545 |
|
---|
2546 | if (!subfile_wanted_p (subentry))
|
---|
2547 | {
|
---|
2548 | FREEA (subentry->strings);
|
---|
2549 | free (subentry->symbols);
|
---|
2550 | free (subentry);
|
---|
2551 | }
|
---|
2552 | else
|
---|
2553 | {
|
---|
2554 | enter_file_symbols (subentry);
|
---|
2555 |
|
---|
2556 | if (*prev_addr)
|
---|
2557 | (*prev_addr)->chain = subentry;
|
---|
2558 | else
|
---|
2559 | entry->subfiles = subentry;
|
---|
2560 | *prev_addr = subentry;
|
---|
2561 | FREEA (subentry->strings);
|
---|
2562 | }
|
---|
2563 | }
|
---|
2564 |
|
---|
2565 | /* Search a library that has no __.SYMDEF.
|
---|
2566 | ENTRY is the library's file_entry.
|
---|
2567 | DESC is the descriptor it is open on. */
|
---|
2568 |
|
---|
2569 | void
|
---|
2570 | linear_library (desc, entry)
|
---|
2571 | int desc;
|
---|
2572 | struct file_entry *entry;
|
---|
2573 | {
|
---|
2574 | struct file_entry *prev = 0;
|
---|
2575 | register int this_subfile_offset = SARMAG;
|
---|
2576 |
|
---|
2577 | while (undefined_global_sym_count || common_defined_global_count)
|
---|
2578 | {
|
---|
2579 | int member_length;
|
---|
2580 | register struct file_entry *subentry;
|
---|
2581 |
|
---|
2582 | subentry = decode_library_subfile (desc, entry, this_subfile_offset,
|
---|
2583 | &member_length);
|
---|
2584 | if (!subentry) return;
|
---|
2585 |
|
---|
2586 | process_subentry (desc, subentry, entry, &prev);
|
---|
2587 | this_subfile_offset += member_length + sizeof (struct ar_hdr);
|
---|
2588 | if (this_subfile_offset & 1) this_subfile_offset++;
|
---|
2589 | }
|
---|
2590 | }
|
---|
2591 | |
---|
2592 |
|
---|
2593 | /* ENTRY is an entry for a library member.
|
---|
2594 | Its symbols have been read into core, but not entered.
|
---|
2595 | Return nonzero if we ought to load this member. */
|
---|
2596 |
|
---|
2597 | int
|
---|
2598 | subfile_wanted_p (entry)
|
---|
2599 | struct file_entry *entry;
|
---|
2600 | {
|
---|
2601 | register struct nlist *p;
|
---|
2602 | register struct nlist *end
|
---|
2603 | = entry->symbols + entry->syms_size / sizeof (struct nlist);
|
---|
2604 |
|
---|
2605 | for (p = entry->symbols; p < end; p++)
|
---|
2606 | {
|
---|
2607 | register int type = p->n_type;
|
---|
2608 | register char *name = p->n_un.n_strx + entry->strings;
|
---|
2609 |
|
---|
2610 | /* If the symbol has an interesting definition, we could
|
---|
2611 | potentially want it. */
|
---|
2612 | if (((type & N_EXT) || WEAK_SYMBOL (type))
|
---|
2613 | && (type != (N_UNDF | N_EXT) || p->n_value)
|
---|
2614 | && (type != (N_WEAKU | N_EXT) || p->n_value)
|
---|
2615 | && !SET_ELEMENT_P (type)
|
---|
2616 | && !set_element_prefixed_p (name))
|
---|
2617 | {
|
---|
2618 | register symbol *sp = getsym_soft (name);
|
---|
2619 |
|
---|
2620 | /* If this symbol has not been hashed, we can't be looking for it. */
|
---|
2621 |
|
---|
2622 | if (!sp) continue;
|
---|
2623 |
|
---|
2624 | if ((sp->referenced && !sp->defined)
|
---|
2625 | /* NB. This needs to be changed so that, e.g., "int pipe;" won't import
|
---|
2626 | pipe() from the library. But the bug fix kingdon made was wrong. */
|
---|
2627 | || (sp->defined && sp->max_common_size
|
---|
2628 | && type != (N_INDR | N_EXT)))
|
---|
2629 | {
|
---|
2630 | /* This is a symbol we are looking for. It is either
|
---|
2631 | not yet defined or defined as a common. */
|
---|
2632 | if (type == (N_UNDF | N_EXT))
|
---|
2633 | {
|
---|
2634 | /* Symbol being defined as common.
|
---|
2635 | Remember this, but don't load subfile just for this. */
|
---|
2636 |
|
---|
2637 | /* If it didn't used to be common, up the count of
|
---|
2638 | common symbols. */
|
---|
2639 | if (!sp->max_common_size)
|
---|
2640 | common_defined_global_count++;
|
---|
2641 |
|
---|
2642 | if (sp->max_common_size < p->n_value)
|
---|
2643 | sp->max_common_size = p->n_value;
|
---|
2644 | if (!sp->defined)
|
---|
2645 | undefined_global_sym_count--;
|
---|
2646 | sp->defined = 1;
|
---|
2647 | continue;
|
---|
2648 | }
|
---|
2649 |
|
---|
2650 | if (write_map)
|
---|
2651 | {
|
---|
2652 | print_file_name (entry, stdout);
|
---|
2653 | fprintf (stdout, " needed due to %s\n", sp->name);
|
---|
2654 | }
|
---|
2655 | return 1;
|
---|
2656 | }
|
---|
2657 | }
|
---|
2658 | }
|
---|
2659 |
|
---|
2660 | return 0;
|
---|
2661 | }
|
---|
2662 | |
---|
2663 |
|
---|
2664 | void consider_file_section_lengths (), relocate_file_addresses ();
|
---|
2665 |
|
---|
2666 | /* Having entered all the global symbols and found the sizes of sections
|
---|
2667 | of all files to be linked, make all appropriate deductions from this data.
|
---|
2668 |
|
---|
2669 | We propagate global symbol values from definitions to references.
|
---|
2670 | We compute the layout of the output file and where each input file's
|
---|
2671 | contents fit into it. */
|
---|
2672 |
|
---|
2673 | void
|
---|
2674 | digest_symbols (void)
|
---|
2675 | {
|
---|
2676 | register int i;
|
---|
2677 | int setv_fill_count = 0;
|
---|
2678 |
|
---|
2679 | if (trace_files)
|
---|
2680 | fprintf (stderr, "Digesting symbol information:\n\n");
|
---|
2681 |
|
---|
2682 | /* Initialize the text_start address; this depends on the output file formats. */
|
---|
2683 |
|
---|
2684 | initialize_text_start ();
|
---|
2685 |
|
---|
2686 | text_size = text_header_size;
|
---|
2687 |
|
---|
2688 | /* Compute total size of sections */
|
---|
2689 |
|
---|
2690 | each_file (consider_file_section_lengths, 0);
|
---|
2691 |
|
---|
2692 | /* If necessary, pad text section to full page in the file.
|
---|
2693 | Include the padding in the text segment size. */
|
---|
2694 |
|
---|
2695 | if (output_style == OUTPUT_READONLY_TEXT || output_style == OUTPUT_DEMAND_PAGED)
|
---|
2696 | {
|
---|
2697 | text_pad = ((text_size + page_size - 1) & (- page_size)) - text_size;
|
---|
2698 | text_size += text_pad;
|
---|
2699 | }
|
---|
2700 |
|
---|
2701 | /* Now that the text_size is known, initialize the data start address;
|
---|
2702 | this depends on text_size as well as the output file format. */
|
---|
2703 |
|
---|
2704 | initialize_data_start ();
|
---|
2705 |
|
---|
2706 | /* Make sure the set vectors are aligned properly. */
|
---|
2707 | {
|
---|
2708 | int new_data_size = ((data_size + sizeof(unsigned long) - 1)
|
---|
2709 | & ~(sizeof(unsigned long)-1));
|
---|
2710 |
|
---|
2711 | set_sect_pad += new_data_size - data_size;
|
---|
2712 | data_size = new_data_size;
|
---|
2713 | }
|
---|
2714 |
|
---|
2715 | /* Set up the set element vector */
|
---|
2716 |
|
---|
2717 | if (output_style != OUTPUT_RELOCATABLE)
|
---|
2718 | {
|
---|
2719 | /* The set sector size is the number of set elements + a word
|
---|
2720 | for each symbol for the length word at the beginning of the
|
---|
2721 | vector, plus a word for each symbol for a zero at the end of
|
---|
2722 | the vector (for incremental linking). */
|
---|
2723 | set_sect_size
|
---|
2724 | = (set_symbol_count + 2 * set_vector_count) * sizeof (unsigned long);
|
---|
2725 | set_sect_start = data_start + data_size;
|
---|
2726 | data_size += set_sect_size;
|
---|
2727 | set_vectors = (unsigned long *) xmalloc (set_sect_size);
|
---|
2728 | set_reloc = (int *) xmalloc (set_sect_size / sizeof (unsigned long)
|
---|
2729 | * sizeof (int));
|
---|
2730 | setv_fill_count = 0;
|
---|
2731 | }
|
---|
2732 |
|
---|
2733 | /* Make sure bss starts out aligned as much as anyone can want. */
|
---|
2734 | {
|
---|
2735 | int new_data_size = (data_size + SECTION_ALIGN_MASK) & ~SECTION_ALIGN_MASK;
|
---|
2736 |
|
---|
2737 | data_pad += new_data_size - data_size;
|
---|
2738 | data_size = new_data_size;
|
---|
2739 | }
|
---|
2740 |
|
---|
2741 | /* Compute start addresses of each file's sections and symbols. */
|
---|
2742 |
|
---|
2743 | each_full_file (relocate_file_addresses, 0);
|
---|
2744 |
|
---|
2745 | /* Now, for each symbol, verify that it is defined globally at most once.
|
---|
2746 | Put the global value into the symbol entry.
|
---|
2747 | Common symbols are allocated here, in the BSS section.
|
---|
2748 | Each defined symbol is given a '->defined' field
|
---|
2749 | which is the correct N_ code for its definition,
|
---|
2750 | except in the case of common symbols with -r.
|
---|
2751 | Then make all the references point at the symbol entry
|
---|
2752 | instead of being chained together. */
|
---|
2753 |
|
---|
2754 | defined_global_sym_count = 0;
|
---|
2755 |
|
---|
2756 | for (i = 0; i < TABSIZE; i++)
|
---|
2757 | {
|
---|
2758 | register symbol *sp;
|
---|
2759 | for (sp = symtab[i]; sp; sp = sp->link)
|
---|
2760 | {
|
---|
2761 | /* For each symbol */
|
---|
2762 | register struct nlist *p, *next;
|
---|
2763 | int defs = 0, com = sp->max_common_size;
|
---|
2764 | struct nlist *first_definition;
|
---|
2765 | for (p = sp->refs; p; p = next)
|
---|
2766 | {
|
---|
2767 | register int type = p->n_type;
|
---|
2768 |
|
---|
2769 | if (SET_ELEMENT_P (type))
|
---|
2770 | {
|
---|
2771 | if (output_style == OUTPUT_RELOCATABLE)
|
---|
2772 | fatal ("internal: global ref to set element with -r");
|
---|
2773 | if (!defs++)
|
---|
2774 | {
|
---|
2775 | sp->value = set_sect_start
|
---|
2776 | + setv_fill_count++ * sizeof (unsigned long);
|
---|
2777 | sp->defined = N_SETV | N_EXT;
|
---|
2778 | first_definition = p;
|
---|
2779 | }
|
---|
2780 | else if ((sp->defined & ~N_EXT) != N_SETV)
|
---|
2781 | {
|
---|
2782 | sp->multiply_defined = 1;
|
---|
2783 | multiple_def_count++;
|
---|
2784 | }
|
---|
2785 | set_reloc[setv_fill_count] = TYPE_OF_SET_ELEMENT (type);
|
---|
2786 | if ((type & ~N_EXT) != N_SETA)
|
---|
2787 | data_reloc_size += sizeof (struct relocation_info);
|
---|
2788 | set_vectors[setv_fill_count++] = p->n_value;
|
---|
2789 | }
|
---|
2790 | else if ((type & N_EXT) && type != (N_UNDF | N_EXT)
|
---|
2791 | && type != (N_IMP1 | N_EXT))
|
---|
2792 | {
|
---|
2793 | /* non-common definition */
|
---|
2794 | if (defs++ && sp->value != p->n_value)
|
---|
2795 | {
|
---|
2796 | sp->multiply_defined = 1;
|
---|
2797 | multiple_def_count++;
|
---|
2798 | }
|
---|
2799 | sp->value = p->n_value;
|
---|
2800 | sp->defined = type;
|
---|
2801 | first_definition = p;
|
---|
2802 | }
|
---|
2803 | next = (struct nlist *) p->n_un.n_name;
|
---|
2804 | p->n_un.n_name = (char *) sp;
|
---|
2805 | }
|
---|
2806 | /* Allocate as common if defined as common and not defined for real */
|
---|
2807 | if (com && !defs)
|
---|
2808 | {
|
---|
2809 | if (output_style != OUTPUT_RELOCATABLE || force_common_definition)
|
---|
2810 | {
|
---|
2811 | int align = sizeof (int);
|
---|
2812 |
|
---|
2813 | /* Round up to nearest sizeof (int). I don't know
|
---|
2814 | whether this is necessary or not (given that
|
---|
2815 | alignment is taken care of later), but it's
|
---|
2816 | traditional, so I'll leave it in. Note that if
|
---|
2817 | this size alignment is ever removed, ALIGN above
|
---|
2818 | will have to be initialized to 1 instead of
|
---|
2819 | sizeof (int). */
|
---|
2820 |
|
---|
2821 | com = (com + sizeof (int) - 1) & (- sizeof (int));
|
---|
2822 |
|
---|
2823 | while (!(com & align))
|
---|
2824 | align <<= 1;
|
---|
2825 |
|
---|
2826 | align = align > MAX_ALIGNMENT ? MAX_ALIGNMENT : align;
|
---|
2827 |
|
---|
2828 | bss_size = ((((bss_size + data_size + data_start)
|
---|
2829 | + (align - 1)) & (- align))
|
---|
2830 | - data_size - data_start);
|
---|
2831 |
|
---|
2832 | sp->value = data_start + data_size + bss_size;
|
---|
2833 | sp->defined = N_BSS | N_EXT;
|
---|
2834 | bss_size += com;
|
---|
2835 | if (write_map)
|
---|
2836 | printf ("Allocating common %s: %x at %lx\n",
|
---|
2837 | sp->name, com, sp->value);
|
---|
2838 | }
|
---|
2839 | else
|
---|
2840 | {
|
---|
2841 | sp->defined = 0;
|
---|
2842 | undefined_global_sym_count++;
|
---|
2843 | }
|
---|
2844 | }
|
---|
2845 | /* Set length word at front of vector and zero byte at end.
|
---|
2846 | Reverse the vector itself to put it in file order. */
|
---|
2847 | if ((sp->defined & ~N_EXT) == N_SETV)
|
---|
2848 | {
|
---|
2849 | unsigned long length_word_index
|
---|
2850 | = (sp->value - set_sect_start) / sizeof (unsigned long);
|
---|
2851 | unsigned long i, tmp;
|
---|
2852 |
|
---|
2853 | set_reloc[length_word_index] = N_ABS;
|
---|
2854 | set_vectors[length_word_index]
|
---|
2855 | = setv_fill_count - 1 - length_word_index;
|
---|
2856 |
|
---|
2857 | /* Reverse the vector. */
|
---|
2858 | for (i = 1;
|
---|
2859 | i < (setv_fill_count - length_word_index - 1) / 2 + 1;
|
---|
2860 | i++)
|
---|
2861 | {
|
---|
2862 | tmp = set_reloc[length_word_index + i];
|
---|
2863 | set_reloc[length_word_index + i]
|
---|
2864 | = set_reloc[setv_fill_count - i];
|
---|
2865 | set_reloc[setv_fill_count - i] = (int)tmp;
|
---|
2866 |
|
---|
2867 | tmp = set_vectors[length_word_index + i];
|
---|
2868 | set_vectors[length_word_index + i]
|
---|
2869 | = set_vectors[setv_fill_count - i];
|
---|
2870 | set_vectors[setv_fill_count - i] = tmp;
|
---|
2871 | }
|
---|
2872 |
|
---|
2873 | set_reloc[setv_fill_count] = N_ABS;
|
---|
2874 | set_vectors[setv_fill_count++] = 0;
|
---|
2875 | }
|
---|
2876 | if (!sp->defined && WEAK_SYMBOL (sp->weak))
|
---|
2877 | {
|
---|
2878 | sp->defined = N_ABS;
|
---|
2879 | sp->value = 0;
|
---|
2880 | undefined_global_sym_count--;
|
---|
2881 | }
|
---|
2882 | if (sp->defined)
|
---|
2883 | defined_global_sym_count++;
|
---|
2884 | }
|
---|
2885 | }
|
---|
2886 |
|
---|
2887 | /* Make sure end of bss is aligned as much as anyone can want. */
|
---|
2888 |
|
---|
2889 | bss_size = (bss_size + SECTION_ALIGN_MASK) & ~SECTION_ALIGN_MASK;
|
---|
2890 |
|
---|
2891 | /* Give values to _end and friends. */
|
---|
2892 | {
|
---|
2893 | int end_value = data_start + data_size + bss_size;
|
---|
2894 | if (end_symbol)
|
---|
2895 | end_symbol->value = end_value;
|
---|
2896 | if (end_symbol_alt)
|
---|
2897 | end_symbol_alt->value = end_value;
|
---|
2898 | }
|
---|
2899 |
|
---|
2900 | {
|
---|
2901 | int etext_value = text_size + text_start;
|
---|
2902 | if (etext_symbol)
|
---|
2903 | etext_symbol->value = etext_value;
|
---|
2904 | if (etext_symbol_alt)
|
---|
2905 | etext_symbol_alt->value = etext_value;
|
---|
2906 | }
|
---|
2907 |
|
---|
2908 | {
|
---|
2909 | int edata_value = data_start + data_size;
|
---|
2910 | if (edata_symbol)
|
---|
2911 | edata_symbol->value = edata_value;
|
---|
2912 | if (edata_symbol_alt)
|
---|
2913 | edata_symbol_alt->value = edata_value;
|
---|
2914 | }
|
---|
2915 |
|
---|
2916 | /* Figure the data_pad now, so that it overlaps with the bss addresses. */
|
---|
2917 |
|
---|
2918 | {
|
---|
2919 | /* The amount of data_pad that we are computing now. This is the
|
---|
2920 | part which overlaps with bss. What was computed previously
|
---|
2921 | goes before bss. */
|
---|
2922 | int data_pad_additional = 0;
|
---|
2923 |
|
---|
2924 | if (specified_data_size && specified_data_size > data_size)
|
---|
2925 | data_pad_additional = specified_data_size - data_size;
|
---|
2926 |
|
---|
2927 | if (output_style == OUTPUT_DEMAND_PAGED)
|
---|
2928 | data_pad_additional =
|
---|
2929 | ((data_pad_additional + data_size + page_size - 1) & (- page_size)) - data_size;
|
---|
2930 |
|
---|
2931 | bss_size -= data_pad_additional;
|
---|
2932 | if (bss_size < 0) bss_size = 0;
|
---|
2933 |
|
---|
2934 | data_size += data_pad_additional;
|
---|
2935 |
|
---|
2936 | data_pad += data_pad_additional;
|
---|
2937 | }
|
---|
2938 | }
|
---|
2939 | |
---|
2940 |
|
---|
2941 | /* Accumulate the section sizes of input file ENTRY
|
---|
2942 | into the section sizes of the output file. */
|
---|
2943 |
|
---|
2944 | void
|
---|
2945 | consider_file_section_lengths (entry)
|
---|
2946 | register struct file_entry *entry;
|
---|
2947 | {
|
---|
2948 | if (entry->just_syms_flag)
|
---|
2949 | return;
|
---|
2950 |
|
---|
2951 | entry->text_start_address = text_size;
|
---|
2952 | /* If there were any vectors, we need to chop them off */
|
---|
2953 | text_size += (entry->text_size + SECTION_ALIGN_MASK) & ~SECTION_ALIGN_MASK;
|
---|
2954 | entry->data_start_address = data_size;
|
---|
2955 | data_size += (entry->data_size + SECTION_ALIGN_MASK) & ~SECTION_ALIGN_MASK;
|
---|
2956 | entry->bss_start_address = bss_size;
|
---|
2957 | bss_size += (entry->bss_size + SECTION_ALIGN_MASK) & ~SECTION_ALIGN_MASK;
|
---|
2958 |
|
---|
2959 | text_reloc_size += entry->text_reloc_size;
|
---|
2960 | data_reloc_size += entry->data_reloc_size;
|
---|
2961 | }
|
---|
2962 |
|
---|
2963 | /* Determine where the sections of ENTRY go into the output file,
|
---|
2964 | whose total section sizes are already known.
|
---|
2965 | Also relocate the addresses of the file's local and debugger symbols. */
|
---|
2966 |
|
---|
2967 | void
|
---|
2968 | relocate_file_addresses (entry)
|
---|
2969 | register struct file_entry *entry;
|
---|
2970 | {
|
---|
2971 | entry->text_start_address += text_start;
|
---|
2972 |
|
---|
2973 | /* Note that `data_start' and `data_size' have not yet been adjusted
|
---|
2974 | for the portion of data_pad which overlaps with bss. If they had
|
---|
2975 | been, we would get the wrong results here. */
|
---|
2976 | entry->data_start_address += data_start;
|
---|
2977 | entry->bss_start_address += data_start + data_size;
|
---|
2978 |
|
---|
2979 | {
|
---|
2980 | register struct nlist *p;
|
---|
2981 | register struct nlist *end
|
---|
2982 | = entry->symbols + entry->syms_size / sizeof (struct nlist);
|
---|
2983 |
|
---|
2984 | for (p = entry->symbols; p < end; p++)
|
---|
2985 | {
|
---|
2986 | /* If this belongs to a section, update it by the section's start address */
|
---|
2987 | register int type = p->n_type & N_TYPE;
|
---|
2988 |
|
---|
2989 | switch (type)
|
---|
2990 | {
|
---|
2991 | case N_TEXT:
|
---|
2992 | case N_SETT:
|
---|
2993 | p->n_value += entry->text_start_address - entry->orig_text_address;
|
---|
2994 | break;
|
---|
2995 | case N_DATA:
|
---|
2996 | case N_SETV:
|
---|
2997 | case N_SETD:
|
---|
2998 | /* Data segment symbol. Subtract the address of the
|
---|
2999 | data segment in the input file, and add the address
|
---|
3000 | of this input file's data segment in the output file. */
|
---|
3001 | p->n_value +=
|
---|
3002 | entry->data_start_address - entry->orig_data_address;
|
---|
3003 | break;
|
---|
3004 | case N_BSS:
|
---|
3005 | case N_SETB:
|
---|
3006 | /* likewise for symbols with value in BSS. */
|
---|
3007 | p->n_value += entry->bss_start_address - entry->orig_bss_address;
|
---|
3008 | break;
|
---|
3009 | }
|
---|
3010 | }
|
---|
3011 | }
|
---|
3012 | }
|
---|
3013 | |
---|
3014 |
|
---|
3015 | void describe_file_sections (), list_file_locals ();
|
---|
3016 |
|
---|
3017 | /* Print a complete or partial map of the output file. */
|
---|
3018 |
|
---|
3019 | void
|
---|
3020 | print_symbols (outfile)
|
---|
3021 | FILE *outfile;
|
---|
3022 | {
|
---|
3023 | register int i;
|
---|
3024 |
|
---|
3025 | fprintf (outfile, "\nFiles:\n\n");
|
---|
3026 |
|
---|
3027 | each_file (describe_file_sections, (int)outfile);
|
---|
3028 |
|
---|
3029 | fprintf (outfile, "\nGlobal symbols:\n\n");
|
---|
3030 |
|
---|
3031 | for (i = 0; i < TABSIZE; i++)
|
---|
3032 | {
|
---|
3033 | register symbol *sp;
|
---|
3034 | for (sp = symtab[i]; sp; sp = sp->link)
|
---|
3035 | {
|
---|
3036 | if (sp->defined == 1)
|
---|
3037 | fprintf (outfile, " %s: common, length 0x%x\n", sp->name, sp->max_common_size);
|
---|
3038 | if (sp->defined)
|
---|
3039 | fprintf (outfile, " %s: 0x%lx\n", sp->name, sp->value);
|
---|
3040 | else if (sp->referenced)
|
---|
3041 | fprintf (outfile, " %s: undefined\n", sp->name);
|
---|
3042 | }
|
---|
3043 | }
|
---|
3044 |
|
---|
3045 | each_file (list_file_locals, (int)outfile);
|
---|
3046 | }
|
---|
3047 |
|
---|
3048 | void
|
---|
3049 | describe_file_sections (entry, outfile)
|
---|
3050 | struct file_entry *entry;
|
---|
3051 | FILE *outfile;
|
---|
3052 | {
|
---|
3053 | fprintf (outfile, " ");
|
---|
3054 | print_file_name (entry, outfile);
|
---|
3055 | if (entry->just_syms_flag)
|
---|
3056 | fprintf (outfile, " symbols only\n");
|
---|
3057 | else
|
---|
3058 | fprintf (outfile, " text %x(%lx), data %x(%lx), bss %x(%lx) hex\n",
|
---|
3059 | entry->text_start_address, entry->text_size,
|
---|
3060 | entry->data_start_address, entry->data_size,
|
---|
3061 | entry->bss_start_address, entry->bss_size);
|
---|
3062 | }
|
---|
3063 |
|
---|
3064 | void
|
---|
3065 | list_file_locals (entry, outfile)
|
---|
3066 | struct file_entry *entry;
|
---|
3067 | FILE *outfile;
|
---|
3068 | {
|
---|
3069 | register struct nlist
|
---|
3070 | *p,
|
---|
3071 | *end = entry->symbols + entry->syms_size / sizeof (struct nlist);
|
---|
3072 |
|
---|
3073 | entry->strings = (char *) ALLOCA (entry->strs_size);
|
---|
3074 | read_entry_strings (file_open (entry), entry);
|
---|
3075 |
|
---|
3076 | fprintf (outfile, "\nLocal symbols of ");
|
---|
3077 | print_file_name (entry, outfile);
|
---|
3078 | fprintf (outfile, ":\n\n");
|
---|
3079 |
|
---|
3080 | for (p = entry->symbols; p < end; p++)
|
---|
3081 | /* If this is a definition,
|
---|
3082 | update it if necessary by this file's start address. */
|
---|
3083 | if (((output_style == OUTPUT_RELOCATABLE) && SET_ELEMENT_P (p->n_type))
|
---|
3084 | || (!(p->n_type & (N_STAB | N_EXT)) && !SET_ELEMENT_P (p->n_type)))
|
---|
3085 | fprintf (outfile, " %s: 0x%lx\n",
|
---|
3086 | entry->strings + p->n_un.n_strx, p->n_value);
|
---|
3087 | else if (SET_ELEMENT_P (p->n_type))
|
---|
3088 | fprintf (outfile, " [set element] %s: 0x%lx\n",
|
---|
3089 | ((symbol *)p->n_un.n_name)->name, p->n_value);
|
---|
3090 |
|
---|
3091 | FREEA (entry->strings);
|
---|
3092 | }
|
---|
3093 |
|
---|
3094 | |
---|
3095 |
|
---|
3096 | /* Static vars for do_warnings and subroutines of it */
|
---|
3097 | int list_unresolved_refs; /* List unresolved refs */
|
---|
3098 | int list_warning_symbols; /* List warning syms */
|
---|
3099 | int list_multiple_defs; /* List multiple definitions */
|
---|
3100 |
|
---|
3101 | /*
|
---|
3102 | * Structure for communication between do_file_warnings and it's
|
---|
3103 | * helper routines. Will in practice be an array of three of these:
|
---|
3104 | * 0) Current line, 1) Next line, 2) Source file info.
|
---|
3105 | */
|
---|
3106 | struct line_debug_entry
|
---|
3107 | {
|
---|
3108 | int line;
|
---|
3109 | char *filename;
|
---|
3110 | struct nlist *sym;
|
---|
3111 | };
|
---|
3112 |
|
---|
3113 | int next_debug_entry (int use_data_symbols, struct line_debug_entry state_pointer[3]);
|
---|
3114 | struct line_debug_entry * init_debug_scan (int use_data_symbols, struct file_entry *entry);
|
---|
3115 | int address_to_line (unsigned long address, struct line_debug_entry state_pointer[3]);
|
---|
3116 | void qsort ();
|
---|
3117 | /*
|
---|
3118 | * Helper routines for do_file_warnings.
|
---|
3119 | */
|
---|
3120 |
|
---|
3121 | /* Return an integer less than, equal to, or greater than 0 as per the
|
---|
3122 | relation between the two relocation entries. Used by qsort. */
|
---|
3123 |
|
---|
3124 | int
|
---|
3125 | relocation_entries_relation (rel1, rel2)
|
---|
3126 | struct relocation_info *rel1, *rel2;
|
---|
3127 | {
|
---|
3128 | return RELOC_ADDRESS(rel1) - RELOC_ADDRESS(rel2);
|
---|
3129 | }
|
---|
3130 |
|
---|
3131 | /* Moves to the next debugging symbol in the file. USE_DATA_SYMBOLS
|
---|
3132 | determines the type of the debugging symbol to look for (DSLINE or
|
---|
3133 | SLINE). STATE_POINTER keeps track of the old and new locatiosn in
|
---|
3134 | the file. It assumes that state_pointer[1] is valid; ie
|
---|
3135 | that it.sym points into some entry in the symbol table. If
|
---|
3136 | state_pointer[1].sym == 0, this routine should not be called. */
|
---|
3137 |
|
---|
3138 | int
|
---|
3139 | next_debug_entry (use_data_symbols, state_pointer)
|
---|
3140 | register int use_data_symbols;
|
---|
3141 | /* Next must be passed by reference! */
|
---|
3142 | struct line_debug_entry state_pointer[3];
|
---|
3143 | {
|
---|
3144 | register struct line_debug_entry
|
---|
3145 | *current = state_pointer,
|
---|
3146 | *next = state_pointer + 1,
|
---|
3147 | /* Used to store source file */
|
---|
3148 | *source = state_pointer + 2;
|
---|
3149 | struct file_entry *entry = (struct file_entry *) source->sym;
|
---|
3150 |
|
---|
3151 | current->sym = next->sym;
|
---|
3152 | current->line = next->line;
|
---|
3153 | current->filename = next->filename;
|
---|
3154 |
|
---|
3155 | while (++(next->sym) < (entry->symbols
|
---|
3156 | + entry->syms_size/sizeof (struct nlist)))
|
---|
3157 | {
|
---|
3158 | /* n_type is a char, and N_SOL, N_EINCL and N_BINCL are > 0x80, so
|
---|
3159 | * may look negative...therefore, must mask to low bits
|
---|
3160 | */
|
---|
3161 | switch (next->sym->n_type & 0xff)
|
---|
3162 | {
|
---|
3163 | case N_SLINE:
|
---|
3164 | if (use_data_symbols) continue;
|
---|
3165 | next->line = next->sym->n_desc;
|
---|
3166 | return 1;
|
---|
3167 | case N_DSLINE:
|
---|
3168 | if (!use_data_symbols) continue;
|
---|
3169 | next->line = next->sym->n_desc;
|
---|
3170 | return 1;
|
---|
3171 | #ifdef HAVE_SUN_STABS
|
---|
3172 | case N_EINCL:
|
---|
3173 | next->filename = source->filename;
|
---|
3174 | continue;
|
---|
3175 | #endif
|
---|
3176 | case N_SO:
|
---|
3177 | source->filename = next->sym->n_un.n_strx + entry->strings;
|
---|
3178 | source->line++;
|
---|
3179 | #ifdef HAVE_SUN_STABS
|
---|
3180 | case N_BINCL:
|
---|
3181 | #endif
|
---|
3182 | case N_SOL:
|
---|
3183 | next->filename
|
---|
3184 | = next->sym->n_un.n_strx + entry->strings;
|
---|
3185 | default:
|
---|
3186 | continue;
|
---|
3187 | }
|
---|
3188 | }
|
---|
3189 | next->sym = (struct nlist *) 0;
|
---|
3190 | return 0;
|
---|
3191 | }
|
---|
3192 |
|
---|
3193 | /* Create a structure to save the state of a scan through the debug
|
---|
3194 | symbols. USE_DATA_SYMBOLS is set if we should be scanning for
|
---|
3195 | DSLINE's instead of SLINE's. entry is the file entry which points
|
---|
3196 | at the symbols to use. */
|
---|
3197 |
|
---|
3198 | struct line_debug_entry *
|
---|
3199 | init_debug_scan (use_data_symbols, entry)
|
---|
3200 | int use_data_symbols;
|
---|
3201 | struct file_entry *entry;
|
---|
3202 | {
|
---|
3203 | struct line_debug_entry
|
---|
3204 | *state_pointer
|
---|
3205 | = (struct line_debug_entry *)
|
---|
3206 | xmalloc (3 * sizeof (struct line_debug_entry));
|
---|
3207 | register struct line_debug_entry
|
---|
3208 | *current = state_pointer,
|
---|
3209 | *next = state_pointer + 1,
|
---|
3210 | *source = state_pointer + 2; /* Used to store source file */
|
---|
3211 |
|
---|
3212 | struct nlist *tmp;
|
---|
3213 |
|
---|
3214 | for (tmp = entry->symbols;
|
---|
3215 | tmp < (entry->symbols
|
---|
3216 | + entry->syms_size/sizeof (struct nlist));
|
---|
3217 | tmp++)
|
---|
3218 | if (tmp->n_type == (int) N_SO)
|
---|
3219 | break;
|
---|
3220 |
|
---|
3221 | if (tmp >= (entry->symbols
|
---|
3222 | + entry->syms_size/sizeof (struct nlist)))
|
---|
3223 | {
|
---|
3224 | /* I believe this translates to "We lose" */
|
---|
3225 | current->filename = next->filename = entry->filename;
|
---|
3226 | current->line = next->line = -1;
|
---|
3227 | current->sym = next->sym = (struct nlist *) 0;
|
---|
3228 | return state_pointer;
|
---|
3229 | }
|
---|
3230 |
|
---|
3231 | next->line = source->line = 0;
|
---|
3232 | next->filename = source->filename
|
---|
3233 | = (tmp->n_un.n_strx + entry->strings);
|
---|
3234 | source->sym = (struct nlist *) entry;
|
---|
3235 | next->sym = tmp;
|
---|
3236 |
|
---|
3237 | next_debug_entry (use_data_symbols, state_pointer); /* To setup next */
|
---|
3238 |
|
---|
3239 | if (!next->sym) /* No line numbers for this section; */
|
---|
3240 | /* setup output results as appropriate */
|
---|
3241 | {
|
---|
3242 | if (source->line)
|
---|
3243 | {
|
---|
3244 | current->filename = source->filename = entry->filename;
|
---|
3245 | current->line = -1; /* Don't print lineno */
|
---|
3246 | }
|
---|
3247 | else
|
---|
3248 | {
|
---|
3249 | current->filename = source->filename;
|
---|
3250 | current->line = 0;
|
---|
3251 | }
|
---|
3252 | return state_pointer;
|
---|
3253 | }
|
---|
3254 |
|
---|
3255 |
|
---|
3256 | next_debug_entry (use_data_symbols, state_pointer); /* To setup current */
|
---|
3257 |
|
---|
3258 | return state_pointer;
|
---|
3259 | }
|
---|
3260 |
|
---|
3261 | /* Takes an ADDRESS (in either text or data space) and a STATE_POINTER
|
---|
3262 | which describes the current location in the implied scan through
|
---|
3263 | the debug symbols within the file which ADDRESS is within, and
|
---|
3264 | returns the source line number which corresponds to ADDRESS. */
|
---|
3265 |
|
---|
3266 | int
|
---|
3267 | address_to_line (address, state_pointer)
|
---|
3268 | unsigned long address;
|
---|
3269 | /* Next must be passed by reference! */
|
---|
3270 | struct line_debug_entry state_pointer[3];
|
---|
3271 | {
|
---|
3272 | struct line_debug_entry
|
---|
3273 | *current = state_pointer,
|
---|
3274 | *next = state_pointer + 1;
|
---|
3275 | struct line_debug_entry *tmp_pointer;
|
---|
3276 |
|
---|
3277 | int use_data_symbols;
|
---|
3278 |
|
---|
3279 | if (next->sym)
|
---|
3280 | use_data_symbols = (next->sym->n_type & ~N_EXT) == N_DATA;
|
---|
3281 | else
|
---|
3282 | return current->line;
|
---|
3283 |
|
---|
3284 | /* Go back to the beginning if we've already passed it. */
|
---|
3285 | if (current->sym->n_value > address)
|
---|
3286 | {
|
---|
3287 | tmp_pointer = init_debug_scan (use_data_symbols,
|
---|
3288 | (struct file_entry *)
|
---|
3289 | ((state_pointer + 2)->sym));
|
---|
3290 | state_pointer[0] = tmp_pointer[0];
|
---|
3291 | state_pointer[1] = tmp_pointer[1];
|
---|
3292 | state_pointer[2] = tmp_pointer[2];
|
---|
3293 | free (tmp_pointer);
|
---|
3294 | }
|
---|
3295 |
|
---|
3296 | /* If we're still in a bad way, return -1, meaning invalid line. */
|
---|
3297 | if (current->sym->n_value > address)
|
---|
3298 | return -1;
|
---|
3299 |
|
---|
3300 | while (next->sym
|
---|
3301 | && next->sym->n_value <= address
|
---|
3302 | && next_debug_entry (use_data_symbols, state_pointer))
|
---|
3303 | ;
|
---|
3304 | return current->line;
|
---|
3305 | }
|
---|
3306 |
|
---|
3307 |
|
---|
3308 | /* Macros for manipulating bitvectors. */
|
---|
3309 | #define BIT_SET_P(bv, index) ((bv)[(index) >> 3] & 1 << ((index) & 0x7))
|
---|
3310 | #define SET_BIT(bv, index) ((bv)[(index) >> 3] |= 1 << ((index) & 0x7))
|
---|
3311 |
|
---|
3312 | /* This routine will scan through the relocation data of file ENTRY,
|
---|
3313 | printing out references to undefined symbols and references to
|
---|
3314 | symbols defined in files with N_WARNING symbols. If DATA_SEGMENT
|
---|
3315 | is non-zero, it will scan the data relocation segment (and use
|
---|
3316 | N_DSLINE symbols to track line number); otherwise it will scan the
|
---|
3317 | text relocation segment. Warnings will be printed on the output
|
---|
3318 | stream OUTFILE. Eventually, every nlist symbol mapped through will
|
---|
3319 | be marked in the NLIST_BITVECTOR, so we don't repeat ourselves when
|
---|
3320 | we scan the nlists themselves. */
|
---|
3321 |
|
---|
3322 | void
|
---|
3323 | do_relocation_warnings (entry, data_segment, outfile, nlist_bitvector)
|
---|
3324 | struct file_entry *entry;
|
---|
3325 | int data_segment;
|
---|
3326 | FILE *outfile;
|
---|
3327 | unsigned char *nlist_bitvector;
|
---|
3328 | {
|
---|
3329 | struct relocation_info
|
---|
3330 | *reloc_start = data_segment ? entry->datarel : entry->textrel,
|
---|
3331 | *reloc;
|
---|
3332 | int reloc_size
|
---|
3333 | = ((data_segment ? entry->data_reloc_size : entry->text_reloc_size)
|
---|
3334 | / sizeof (struct relocation_info));
|
---|
3335 | int start_of_segment
|
---|
3336 | = (data_segment ? entry->data_start_address : entry->text_start_address);
|
---|
3337 | struct nlist *start_of_syms = entry->symbols;
|
---|
3338 | struct line_debug_entry *state_pointer
|
---|
3339 | = init_debug_scan (data_segment != 0, entry);
|
---|
3340 | register struct line_debug_entry *current = state_pointer;
|
---|
3341 | /* Assigned to generally static values; should not be written into. */
|
---|
3342 | char *errfmt;
|
---|
3343 | /* Assigned to alloca'd values cand copied into; should be freed
|
---|
3344 | when done. */
|
---|
3345 | char *errmsg;
|
---|
3346 | int invalidate_line_number;
|
---|
3347 |
|
---|
3348 | /* We need to sort the relocation info here. Sheesh, so much effort
|
---|
3349 | for one lousy error optimization. */
|
---|
3350 |
|
---|
3351 | qsort (reloc_start, reloc_size, sizeof (struct relocation_info),
|
---|
3352 | (int (*)(const void *, const void *))relocation_entries_relation);
|
---|
3353 |
|
---|
3354 | for (reloc = reloc_start;
|
---|
3355 | reloc < (reloc_start + reloc_size);
|
---|
3356 | reloc++)
|
---|
3357 | {
|
---|
3358 | register struct nlist *s;
|
---|
3359 | register symbol *g;
|
---|
3360 |
|
---|
3361 | /* If the relocation isn't resolved through a symbol, continue */
|
---|
3362 | if (!RELOC_EXTERN_P(reloc))
|
---|
3363 | continue;
|
---|
3364 |
|
---|
3365 | s = &(entry->symbols[RELOC_SYMBOL(reloc)]);
|
---|
3366 |
|
---|
3367 | /* Local symbols shouldn't ever be used by relocation info, so
|
---|
3368 | the next should be safe.
|
---|
3369 | This is, of course, wrong. References to local BSS symbols can be
|
---|
3370 | the targets of relocation info, and they can (must) be
|
---|
3371 | resolved through symbols. However, these must be defined properly,
|
---|
3372 | (the assembler would have caught it otherwise), so we can
|
---|
3373 | ignore these cases. */
|
---|
3374 | if (!(s->n_type & N_EXT))
|
---|
3375 | continue;
|
---|
3376 |
|
---|
3377 | g = (symbol *) s->n_un.n_name;
|
---|
3378 | errmsg = 0;
|
---|
3379 |
|
---|
3380 | if (!g->defined && list_unresolved_refs) /* Reference */
|
---|
3381 | {
|
---|
3382 | /* Mark as being noted by relocation warning pass. */
|
---|
3383 | SET_BIT (nlist_bitvector, s - start_of_syms);
|
---|
3384 |
|
---|
3385 | if (g->undef_refs >= MAX_UREFS_PRINTED) /* Listed too many */
|
---|
3386 | continue;
|
---|
3387 |
|
---|
3388 | /* Undefined symbol which we should mention */
|
---|
3389 |
|
---|
3390 | if (++(g->undef_refs) == MAX_UREFS_PRINTED)
|
---|
3391 | {
|
---|
3392 | errfmt = "More undefined symbol %s refs follow";
|
---|
3393 | invalidate_line_number = 1;
|
---|
3394 | }
|
---|
3395 | else
|
---|
3396 | {
|
---|
3397 | errfmt = "Undefined symbol %s referenced from %s segment";
|
---|
3398 | invalidate_line_number = 0;
|
---|
3399 | }
|
---|
3400 | }
|
---|
3401 | else /* Defined */
|
---|
3402 | {
|
---|
3403 | /* Potential symbol warning here */
|
---|
3404 | if (!g->warning) continue;
|
---|
3405 |
|
---|
3406 | /* Mark as being noted by relocation warning pass. */
|
---|
3407 | SET_BIT (nlist_bitvector, s - start_of_syms);
|
---|
3408 |
|
---|
3409 | errfmt = 0;
|
---|
3410 | errmsg = g->warning;
|
---|
3411 | invalidate_line_number = 0;
|
---|
3412 | }
|
---|
3413 |
|
---|
3414 |
|
---|
3415 | /* If errfmt == 0, errmsg has already been defined. */
|
---|
3416 | if (errfmt != 0)
|
---|
3417 | {
|
---|
3418 | char *nm;
|
---|
3419 |
|
---|
3420 | if (!demangler || !(nm = (*demangler)(g->name)))
|
---|
3421 | nm = g->name;
|
---|
3422 | errmsg = (char *) xmalloc (strlen (errfmt) + strlen (nm) + 1);
|
---|
3423 | sprintf (errmsg, errfmt, nm, data_segment ? "data" : "text");
|
---|
3424 | if (nm != g->name)
|
---|
3425 | free (nm);
|
---|
3426 | }
|
---|
3427 |
|
---|
3428 | address_to_line (RELOC_ADDRESS (reloc) + start_of_segment,
|
---|
3429 | state_pointer);
|
---|
3430 |
|
---|
3431 | if (current->line >=0)
|
---|
3432 | {
|
---|
3433 | fprintf (outfile, "%s:%d (", current->filename,
|
---|
3434 | invalidate_line_number ? 0 : current->line);
|
---|
3435 | print_file_name (entry, outfile);
|
---|
3436 | fprintf (outfile, "): %s\n", errmsg);
|
---|
3437 | }
|
---|
3438 | else
|
---|
3439 | {
|
---|
3440 | print_file_name(entry, outfile);
|
---|
3441 | fprintf(outfile, ": %s\n", errmsg);
|
---|
3442 | }
|
---|
3443 |
|
---|
3444 | if (errfmt != 0)
|
---|
3445 | free (errmsg);
|
---|
3446 | }
|
---|
3447 |
|
---|
3448 | free (state_pointer);
|
---|
3449 | }
|
---|
3450 |
|
---|
3451 | /* Print on OUTFILE a list of all warnings generated by references
|
---|
3452 | and/or definitions in the file ENTRY. List source file and line
|
---|
3453 | number if possible, just the .o file if not. */
|
---|
3454 |
|
---|
3455 | void
|
---|
3456 | do_file_warnings (entry, outfile)
|
---|
3457 | struct file_entry *entry;
|
---|
3458 | FILE *outfile;
|
---|
3459 | {
|
---|
3460 | int number_of_syms = entry->syms_size / sizeof (struct nlist);
|
---|
3461 | unsigned char *nlist_bitvector
|
---|
3462 | = (unsigned char *) ALLOCA ((number_of_syms >> 3) + 1);
|
---|
3463 | struct line_debug_entry *text_scan, *data_scan;
|
---|
3464 | int i;
|
---|
3465 | char *errfmt, *file_name = NULL;
|
---|
3466 | int line_number = 0;
|
---|
3467 | int dont_allow_symbol_name;
|
---|
3468 |
|
---|
3469 | bzero (nlist_bitvector, (number_of_syms >> 3) + 1);
|
---|
3470 |
|
---|
3471 | /* Read in the files strings if they aren't available */
|
---|
3472 | if (!entry->strings)
|
---|
3473 | {
|
---|
3474 | int desc;
|
---|
3475 |
|
---|
3476 | entry->strings = (char *) ALLOCA (entry->strs_size);
|
---|
3477 | desc = file_open (entry);
|
---|
3478 | read_entry_strings (desc, entry);
|
---|
3479 | }
|
---|
3480 |
|
---|
3481 | read_file_relocation (entry);
|
---|
3482 |
|
---|
3483 | /* Do text warnings based on a scan through the relocation info. */
|
---|
3484 | do_relocation_warnings (entry, 0, outfile, nlist_bitvector);
|
---|
3485 |
|
---|
3486 | /* Do data warnings based on a scan through the relocation info. */
|
---|
3487 | do_relocation_warnings (entry, 1, outfile, nlist_bitvector);
|
---|
3488 |
|
---|
3489 | /* Scan through all of the nlist entries in this file and pick up
|
---|
3490 | anything that the scan through the relocation stuff didn't. */
|
---|
3491 |
|
---|
3492 | text_scan = init_debug_scan (0, entry);
|
---|
3493 | data_scan = init_debug_scan (1, entry);
|
---|
3494 |
|
---|
3495 | for (i = 0; i < number_of_syms; i++)
|
---|
3496 | {
|
---|
3497 | struct nlist *s;
|
---|
3498 | struct glosym *g;
|
---|
3499 |
|
---|
3500 | s = entry->symbols + i;
|
---|
3501 |
|
---|
3502 | if (WEAK_SYMBOL (s->n_type) || !(s->n_type & N_EXT))
|
---|
3503 | continue;
|
---|
3504 |
|
---|
3505 | g = (symbol *) s->n_un.n_name;
|
---|
3506 | dont_allow_symbol_name = 0;
|
---|
3507 |
|
---|
3508 | if (list_multiple_defs && g->multiply_defined)
|
---|
3509 | {
|
---|
3510 | errfmt = "Definition of symbol %s (multiply defined)";
|
---|
3511 | switch (s->n_type)
|
---|
3512 | {
|
---|
3513 | case N_TEXT | N_EXT:
|
---|
3514 | line_number = address_to_line (s->n_value, text_scan);
|
---|
3515 | file_name = text_scan[0].filename;
|
---|
3516 | break;
|
---|
3517 | case N_BSS | N_EXT:
|
---|
3518 | case N_DATA | N_EXT:
|
---|
3519 | line_number = address_to_line (s->n_value, data_scan);
|
---|
3520 | file_name = data_scan[0].filename;
|
---|
3521 | break;
|
---|
3522 | case N_SETA | N_EXT:
|
---|
3523 | case N_SETT | N_EXT:
|
---|
3524 | case N_SETD | N_EXT:
|
---|
3525 | case N_SETB | N_EXT:
|
---|
3526 | if (g->multiply_defined == 2)
|
---|
3527 | continue;
|
---|
3528 | errfmt = "First set element definition of symbol %s (multiply defined)";
|
---|
3529 | break;
|
---|
3530 | default:
|
---|
3531 | continue; /* Don't print out multiple defs
|
---|
3532 | at references. */
|
---|
3533 | }
|
---|
3534 | }
|
---|
3535 | else if (BIT_SET_P (nlist_bitvector, i))
|
---|
3536 | continue;
|
---|
3537 | else if (list_unresolved_refs && !g->defined)
|
---|
3538 | {
|
---|
3539 | if (g->undef_refs >= MAX_UREFS_PRINTED)
|
---|
3540 | continue;
|
---|
3541 |
|
---|
3542 | if (++(g->undef_refs) == MAX_UREFS_PRINTED)
|
---|
3543 | errfmt = "More undefined \"%s\" refs follow";
|
---|
3544 | else
|
---|
3545 | errfmt = "Undefined symbol \"%s\" referenced";
|
---|
3546 | line_number = -1;
|
---|
3547 | }
|
---|
3548 | else if (g->warning)
|
---|
3549 | {
|
---|
3550 | /* There are two cases in which we don't want to
|
---|
3551 | do this. The first is if this is a definition instead of
|
---|
3552 | a reference. The second is if it's the reference used by
|
---|
3553 | the warning stabs itself. */
|
---|
3554 | if (s->n_type != (N_EXT | N_UNDF)
|
---|
3555 | || (i && (s-1)->n_type == N_WARNING))
|
---|
3556 | continue;
|
---|
3557 |
|
---|
3558 | errfmt = g->warning;
|
---|
3559 | line_number = -1;
|
---|
3560 | dont_allow_symbol_name = 1;
|
---|
3561 | }
|
---|
3562 | else
|
---|
3563 | continue;
|
---|
3564 |
|
---|
3565 | if (line_number == -1)
|
---|
3566 | {
|
---|
3567 | print_file_name (entry, outfile);
|
---|
3568 | fprintf (outfile, ": ");
|
---|
3569 | }
|
---|
3570 | else
|
---|
3571 | {
|
---|
3572 | fprintf (outfile, "%s:%d (", file_name, line_number);
|
---|
3573 | print_file_name (entry, outfile);
|
---|
3574 | fprintf (outfile, "): ");
|
---|
3575 | }
|
---|
3576 |
|
---|
3577 | if (dont_allow_symbol_name)
|
---|
3578 | fprintf (outfile, "%s", errfmt);
|
---|
3579 | else
|
---|
3580 | {
|
---|
3581 | char *nm;
|
---|
3582 |
|
---|
3583 | if (!demangler || !(nm = (*demangler)(g->name)))
|
---|
3584 | fprintf (outfile, errfmt, g->name);
|
---|
3585 | else
|
---|
3586 | {
|
---|
3587 | fprintf (outfile, errfmt, nm);
|
---|
3588 | free (nm);
|
---|
3589 | }
|
---|
3590 | }
|
---|
3591 |
|
---|
3592 | fputc ('\n', outfile);
|
---|
3593 | }
|
---|
3594 | free (text_scan);
|
---|
3595 | free (data_scan);
|
---|
3596 | FREEA (entry->strings);
|
---|
3597 | FREEA (nlist_bitvector);
|
---|
3598 | }
|
---|
3599 | |
---|
3600 |
|
---|
3601 | void
|
---|
3602 | do_warnings (outfile)
|
---|
3603 | FILE *outfile;
|
---|
3604 | {
|
---|
3605 | list_unresolved_refs = output_style != OUTPUT_RELOCATABLE && undefined_global_sym_count;
|
---|
3606 | list_warning_symbols = warning_count;
|
---|
3607 | list_multiple_defs = multiple_def_count != 0;
|
---|
3608 |
|
---|
3609 | if (!(list_unresolved_refs ||
|
---|
3610 | list_warning_symbols ||
|
---|
3611 | list_multiple_defs ))
|
---|
3612 | /* No need to run this routine */
|
---|
3613 | return;
|
---|
3614 |
|
---|
3615 | each_file (do_file_warnings, (int)outfile);
|
---|
3616 |
|
---|
3617 | if (list_unresolved_refs || list_multiple_defs)
|
---|
3618 | make_executable = 0;
|
---|
3619 | }
|
---|
3620 | |
---|
3621 |
|
---|
3622 | #ifdef A_OUT
|
---|
3623 |
|
---|
3624 | /* Stuff pertaining to creating a.out files. */
|
---|
3625 |
|
---|
3626 | /* The a.out header. */
|
---|
3627 |
|
---|
3628 | struct exec outheader;
|
---|
3629 |
|
---|
3630 | /* Compute text_start and text_header_size for an a.out file. */
|
---|
3631 |
|
---|
3632 | void
|
---|
3633 | initialize_a_out_text_start (void)
|
---|
3634 | {
|
---|
3635 | int magic = 0;
|
---|
3636 |
|
---|
3637 | switch (output_style)
|
---|
3638 | {
|
---|
3639 | case OUTPUT_RELOCATABLE:
|
---|
3640 | case OUTPUT_WRITABLE_TEXT:
|
---|
3641 | magic = OMAGIC;
|
---|
3642 | break;
|
---|
3643 | case OUTPUT_READONLY_TEXT:
|
---|
3644 | #ifdef NMAGIC
|
---|
3645 | magic = NMAGIC;
|
---|
3646 | break;
|
---|
3647 | #endif
|
---|
3648 | case OUTPUT_DEMAND_PAGED:
|
---|
3649 | magic = ZMAGIC;
|
---|
3650 | break;
|
---|
3651 | default:
|
---|
3652 | fatal ("unknown output style found (bug in ld)", (char *) 0);
|
---|
3653 | break;
|
---|
3654 | }
|
---|
3655 |
|
---|
3656 | /* Determine whether to count the header as part of
|
---|
3657 | the text size, and initialize the text size accordingly.
|
---|
3658 | This depends on the kind of system and on the output format selected. */
|
---|
3659 | N_SET_MAGIC (outheader, magic);
|
---|
3660 | N_SET_MACHTYPE (outheader, M_386);
|
---|
3661 | #ifdef INITIALIZE_HEADER
|
---|
3662 | INITIALIZE_HEADER;
|
---|
3663 | #endif
|
---|
3664 |
|
---|
3665 | text_header_size = sizeof (struct exec);
|
---|
3666 | if (text_header_size <= N_TXTOFF (outheader))
|
---|
3667 | text_header_size = 0;
|
---|
3668 | else
|
---|
3669 | text_header_size -= N_TXTOFF (outheader);
|
---|
3670 |
|
---|
3671 | #ifdef _N_BASEADDR
|
---|
3672 | /* SunOS 4.1 N_TXTADDR depends on the value of outheader.a_entry. */
|
---|
3673 | outheader.a_entry = N_PAGSIZ(outheader);
|
---|
3674 | #endif
|
---|
3675 |
|
---|
3676 | if (!T_flag_specified && output_style != OUTPUT_RELOCATABLE)
|
---|
3677 | text_start = N_TXTADDR (outheader);
|
---|
3678 | }
|
---|
3679 |
|
---|
3680 | /* Compute data_start once text_size is known. */
|
---|
3681 |
|
---|
3682 | void
|
---|
3683 | initialize_a_out_data_start (void)
|
---|
3684 | {
|
---|
3685 | outheader.a_text = text_size;
|
---|
3686 | if (! Tdata_flag_specified)
|
---|
3687 | data_start = N_DATADDR (outheader) + text_start - N_TXTADDR (outheader);
|
---|
3688 | }
|
---|
3689 |
|
---|
3690 | /* Compute offsets of various pieces of the a.out output file. */
|
---|
3691 |
|
---|
3692 | void
|
---|
3693 | compute_a_out_section_offsets (void)
|
---|
3694 | {
|
---|
3695 | outheader.a_data = data_size;
|
---|
3696 | outheader.a_bss = bss_size;
|
---|
3697 | outheader.a_entry = (entry_symbol ? entry_symbol->value
|
---|
3698 | : text_start + text_header_size);
|
---|
3699 |
|
---|
3700 | if (strip_symbols == STRIP_ALL)
|
---|
3701 | nsyms = 0;
|
---|
3702 | else
|
---|
3703 | {
|
---|
3704 | nsyms = (defined_global_sym_count
|
---|
3705 | + undefined_global_sym_count);
|
---|
3706 | if (discard_locals == DISCARD_L)
|
---|
3707 | nsyms += non_L_local_sym_count;
|
---|
3708 | else if (discard_locals == DISCARD_NONE)
|
---|
3709 | nsyms += local_sym_count;
|
---|
3710 | /* One extra for following reference on indirects */
|
---|
3711 | if (output_style == OUTPUT_RELOCATABLE)
|
---|
3712 | nsyms += set_symbol_count + global_indirect_count;
|
---|
3713 | }
|
---|
3714 |
|
---|
3715 | if (strip_symbols == STRIP_NONE)
|
---|
3716 | nsyms += debugger_sym_count;
|
---|
3717 |
|
---|
3718 | outheader.a_syms = nsyms * sizeof (struct nlist);
|
---|
3719 |
|
---|
3720 | if (output_style == OUTPUT_RELOCATABLE || reloc_flag)
|
---|
3721 | {
|
---|
3722 | outheader.a_trsize = text_reloc_size;
|
---|
3723 | outheader.a_drsize = data_reloc_size;
|
---|
3724 | }
|
---|
3725 | else
|
---|
3726 | {
|
---|
3727 | outheader.a_trsize = 0;
|
---|
3728 | outheader.a_drsize = 0;
|
---|
3729 | }
|
---|
3730 |
|
---|
3731 | /* Initialize the various file offsets. */
|
---|
3732 |
|
---|
3733 | output_text_offset = N_TXTOFF (outheader);
|
---|
3734 | #ifdef N_DATOFF
|
---|
3735 | output_data_offset = N_DATOFF (outheader);
|
---|
3736 | #else
|
---|
3737 | output_data_offset = output_text_offset + text_size;
|
---|
3738 | #endif
|
---|
3739 | #ifdef N_TRELOFF
|
---|
3740 | output_trel_offset = N_TRELOFF (outheader);
|
---|
3741 | #else
|
---|
3742 | output_trel_offset = output_data_offset + data_size;
|
---|
3743 | #endif
|
---|
3744 | #ifdef N_DRELOFF
|
---|
3745 | output_drel_offset = N_DRELOFF (outheader);
|
---|
3746 | #else
|
---|
3747 | output_drel_offset = output_trel_offset + text_reloc_size;
|
---|
3748 | #endif
|
---|
3749 | output_syms_offset = N_SYMOFF (outheader);
|
---|
3750 | output_strs_offset = N_STROFF (outheader);
|
---|
3751 | }
|
---|
3752 |
|
---|
3753 | /* Compute more section offsets once the size of the string table is known. */
|
---|
3754 |
|
---|
3755 | void
|
---|
3756 | compute_more_a_out_section_offsets (void)
|
---|
3757 | {
|
---|
3758 | output_symseg_offset = output_strs_offset + output_strs_size;
|
---|
3759 | }
|
---|
3760 |
|
---|
3761 | /* Write the a.out header once everything else is known. */
|
---|
3762 |
|
---|
3763 | void
|
---|
3764 | write_a_out_header (void)
|
---|
3765 | {
|
---|
3766 | lseek (outdesc, 0L, 0);
|
---|
3767 | mywrite (&outheader, sizeof (struct exec), 1, outdesc);
|
---|
3768 | }
|
---|
3769 |
|
---|
3770 | #endif
|
---|
3771 | |
---|
3772 |
|
---|
3773 | /* The following functions are simple switches according to the
|
---|
3774 | output style. */
|
---|
3775 |
|
---|
3776 | /* Compute text_start and text_header_size as appropriate for the
|
---|
3777 | output format. */
|
---|
3778 |
|
---|
3779 | void
|
---|
3780 | initialize_text_start (void)
|
---|
3781 | {
|
---|
3782 | #ifdef A_OUT
|
---|
3783 | if (output_file_type == IS_A_OUT)
|
---|
3784 | {
|
---|
3785 | initialize_a_out_text_start ();
|
---|
3786 | return;
|
---|
3787 | }
|
---|
3788 | #endif
|
---|
3789 | fatal ("unknown output file type (enum file_type)", (char *) 0);
|
---|
3790 | }
|
---|
3791 |
|
---|
3792 | /* Initialize data_start as appropriate to the output format, once text_size
|
---|
3793 | is known. */
|
---|
3794 |
|
---|
3795 | void
|
---|
3796 | initialize_data_start (void)
|
---|
3797 | {
|
---|
3798 | #ifdef A_OUT
|
---|
3799 | if (output_file_type == IS_A_OUT)
|
---|
3800 | {
|
---|
3801 | initialize_a_out_data_start ();
|
---|
3802 | return;
|
---|
3803 | }
|
---|
3804 | #endif
|
---|
3805 | fatal ("unknown output file type (enum file_type)", (char *) 0);
|
---|
3806 | }
|
---|
3807 |
|
---|
3808 | /* Compute offsets of the various sections within the output file. */
|
---|
3809 |
|
---|
3810 | void
|
---|
3811 | compute_section_offsets (void)
|
---|
3812 | {
|
---|
3813 | #ifdef A_OUT
|
---|
3814 | if (output_file_type == IS_A_OUT)
|
---|
3815 | {
|
---|
3816 | compute_a_out_section_offsets ();
|
---|
3817 | return;
|
---|
3818 | }
|
---|
3819 | #endif
|
---|
3820 | fatal ("unknown output file type (enum file_type)", (char *) 0);
|
---|
3821 | }
|
---|
3822 |
|
---|
3823 | /* Compute more section offsets, once the size of the string table
|
---|
3824 | is finalized. */
|
---|
3825 | void
|
---|
3826 | compute_more_section_offsets (void)
|
---|
3827 | {
|
---|
3828 | #ifdef A_OUT
|
---|
3829 | if (output_file_type == IS_A_OUT)
|
---|
3830 | {
|
---|
3831 | compute_more_a_out_section_offsets ();
|
---|
3832 | return;
|
---|
3833 | }
|
---|
3834 | #endif
|
---|
3835 | fatal ("unknown output file type (enum file_type)", (char *) 0);
|
---|
3836 | }
|
---|
3837 |
|
---|
3838 | /* Write the output file header, once everything is known. */
|
---|
3839 | void
|
---|
3840 | write_header (void)
|
---|
3841 | {
|
---|
3842 | #ifdef A_OUT
|
---|
3843 | if (output_file_type == IS_A_OUT)
|
---|
3844 | {
|
---|
3845 | write_a_out_header ();
|
---|
3846 | return;
|
---|
3847 | }
|
---|
3848 | #endif
|
---|
3849 | fatal ("unknown output file type (enum file_type)", (char *) 0);
|
---|
3850 | }
|
---|
3851 | |
---|
3852 |
|
---|
3853 | /* Parse output_filename and decide whether to create an exe file or not */
|
---|
3854 |
|
---|
3855 | void check_exe (void)
|
---|
3856 | {
|
---|
3857 | char *ext;
|
---|
3858 |
|
---|
3859 | if (exe_flag)
|
---|
3860 | {
|
---|
3861 | ext = _getext (output_filename);
|
---|
3862 | if ((ext != NULL) && (stricmp (ext, ".exe") == 0))
|
---|
3863 | {
|
---|
3864 | exe_filename = output_filename;
|
---|
3865 | exe_flag = 0;
|
---|
3866 | } else
|
---|
3867 | {
|
---|
3868 | touch_filename = output_filename;
|
---|
3869 | exe_filename = concat (output_filename, ".exe", NULL);
|
---|
3870 | }
|
---|
3871 | }
|
---|
3872 | else
|
---|
3873 | {
|
---|
3874 | ext = _getext2 (output_filename);
|
---|
3875 | if (stricmp (ext, ".dll") == 0)
|
---|
3876 | {
|
---|
3877 | reloc_flag = 1; dll_flag = 1;
|
---|
3878 | }
|
---|
3879 | else if (stricmp (ext, ".exe") != 0)
|
---|
3880 | {
|
---|
3881 | exe_filename = NULL;
|
---|
3882 | return;
|
---|
3883 | }
|
---|
3884 | exe_filename = output_filename;
|
---|
3885 | }
|
---|
3886 |
|
---|
3887 | /* Create a temporary a.out executable file. */
|
---|
3888 |
|
---|
3889 | output_filename = make_temp_file ("ldXXXXXX");
|
---|
3890 |
|
---|
3891 | if (rsxnt_linked != EMX_DEFAULT && strip_symbols != STRIP_NONE) /* RSXNT */
|
---|
3892 | {
|
---|
3893 | strip_symbols = STRIP_NONE;
|
---|
3894 | emxbind_strip = 1;
|
---|
3895 | }
|
---|
3896 | else if (strip_symbols == STRIP_ALL)
|
---|
3897 | {
|
---|
3898 | strip_symbols = STRIP_DEBUGGER;
|
---|
3899 | emxbind_strip = 1;
|
---|
3900 | }
|
---|
3901 | unlink (exe_filename);
|
---|
3902 | if (touch_filename != NULL)
|
---|
3903 | unlink (touch_filename);
|
---|
3904 | }
|
---|
3905 |
|
---|
3906 | /* Write the output file */
|
---|
3907 |
|
---|
3908 | void
|
---|
3909 | write_output (void)
|
---|
3910 | {
|
---|
3911 | struct stat statbuf;
|
---|
3912 | int filemode, mask;
|
---|
3913 |
|
---|
3914 | /* Remove the old file in case it is owned by someone else.
|
---|
3915 | This prevents spurious "not owner" error messages.
|
---|
3916 | Don't check for errors from unlink; we don't really care
|
---|
3917 | whether it worked.
|
---|
3918 |
|
---|
3919 | Note that this means that if the output file is hard linked,
|
---|
3920 | the other names will still have the old contents. This is
|
---|
3921 | the way Unix ld works; I'm going to consider it a feature. */
|
---|
3922 | (void) unlink (output_filename);
|
---|
3923 |
|
---|
3924 | outdesc = open (output_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
|
---|
3925 | if (outdesc < 0) perror_name (output_filename);
|
---|
3926 |
|
---|
3927 | if (fstat (outdesc, &statbuf) < 0)
|
---|
3928 | perror_name (output_filename);
|
---|
3929 |
|
---|
3930 | filemode = statbuf.st_mode;
|
---|
3931 |
|
---|
3932 | chmod (output_filename, filemode & ~0111);
|
---|
3933 |
|
---|
3934 | if (reloc_flag)
|
---|
3935 | global_indirect_count = 0;
|
---|
3936 |
|
---|
3937 | /* Calculate the offsets of the various pieces of the output file. */
|
---|
3938 | compute_section_offsets ();
|
---|
3939 |
|
---|
3940 | /* Output the text and data segments, relocating as we go. */
|
---|
3941 | write_text ();
|
---|
3942 | write_data ();
|
---|
3943 |
|
---|
3944 | /* Output the merged relocation info, if requested with `-r'. */
|
---|
3945 | if (output_style == OUTPUT_RELOCATABLE || reloc_flag)
|
---|
3946 | write_rel ();
|
---|
3947 |
|
---|
3948 | /* Output the symbol table (both globals and locals). */
|
---|
3949 | write_syms ();
|
---|
3950 |
|
---|
3951 | /* At this point the total size of the symbol table and string table
|
---|
3952 | are finalized. */
|
---|
3953 | compute_more_section_offsets ();
|
---|
3954 |
|
---|
3955 | /* Copy any GDB symbol segments from input files. */
|
---|
3956 | write_symsegs ();
|
---|
3957 |
|
---|
3958 | /* Now that everything is known about the output file, write its header. */
|
---|
3959 | write_header ();
|
---|
3960 |
|
---|
3961 | close (outdesc);
|
---|
3962 |
|
---|
3963 | mask = umask (0);
|
---|
3964 | umask (mask);
|
---|
3965 |
|
---|
3966 | if (chmod (output_filename, filemode | (0111 & ~mask)) == -1)
|
---|
3967 | perror_name (output_filename);
|
---|
3968 |
|
---|
3969 | if (rsxnt_linked == EMX_DEFAULT && exe_filename != NULL)
|
---|
3970 | {
|
---|
3971 | char *nargv[11];
|
---|
3972 | char *freeav[11];
|
---|
3973 | int i, j, saved_errno;
|
---|
3974 |
|
---|
3975 | i = j = 0;
|
---|
3976 | nargv[i++] = "emxbind";
|
---|
3977 | nargv[i++] = "-bq";
|
---|
3978 | if (emxbind_strip)
|
---|
3979 | nargv[i++] = "-s";
|
---|
3980 | if (dll_flag && !def_filename)
|
---|
3981 | gen_deffile();
|
---|
3982 | if (def_filename != NULL)
|
---|
3983 | {
|
---|
3984 | freeav[j++] = nargv[i] = ALLOCA (strlen (def_filename) + 3);
|
---|
3985 | strcpy (nargv[i], "-d");
|
---|
3986 | strcat (nargv[i], def_filename);
|
---|
3987 | i++;
|
---|
3988 | }
|
---|
3989 | else if (dll_flag)
|
---|
3990 | nargv[i++] = "-d";
|
---|
3991 | if (stack_size != 0)
|
---|
3992 | {
|
---|
3993 | freeav[j++] = nargv[i] = ALLOCA (20);
|
---|
3994 | sprintf (nargv[i], "-k0x%x", stack_size);
|
---|
3995 | i++;
|
---|
3996 | }
|
---|
3997 | if (map_flag)
|
---|
3998 | {
|
---|
3999 | if (map_filename == NULL)
|
---|
4000 | {
|
---|
4001 | freeav[j++] = map_filename = ALLOCA (strlen (exe_filename) + 5);
|
---|
4002 | strcpy (map_filename, exe_filename);
|
---|
4003 | _remext (map_filename);
|
---|
4004 | strcat (map_filename, ".map");
|
---|
4005 | }
|
---|
4006 | freeav[j++] = nargv[i] = ALLOCA (strlen (map_filename) + 3);
|
---|
4007 | strcpy (nargv[i], "-m");
|
---|
4008 | strcat (nargv[i], map_filename);
|
---|
4009 | i++;
|
---|
4010 | }
|
---|
4011 | if (res_filename != NULL)
|
---|
4012 | {
|
---|
4013 | freeav[j++] = nargv[i] = ALLOCA (strlen (res_filename) + 3);
|
---|
4014 | strcpy (nargv[i], "-r");
|
---|
4015 | strcat (nargv[i], res_filename);
|
---|
4016 | i++;
|
---|
4017 | }
|
---|
4018 | nargv[i++] = "-o";
|
---|
4019 | nargv[i++] = exe_filename;
|
---|
4020 | nargv[i++] = output_filename;
|
---|
4021 | nargv[i] = NULL;
|
---|
4022 | if (trace_files)
|
---|
4023 | {
|
---|
4024 | fprintf(stderr, "Invoking emxbind:");
|
---|
4025 | for (i = 0; nargv[i]; i++)
|
---|
4026 | fprintf(stderr, " %s", nargv[i]);
|
---|
4027 | fprintf(stderr, "\n");
|
---|
4028 | }
|
---|
4029 | i = spawnvp (P_WAIT, "emxbind", nargv);
|
---|
4030 | saved_errno = errno; unlink (output_filename); errno = saved_errno;
|
---|
4031 | if (i < 0)
|
---|
4032 | perror_name ("emxbind");
|
---|
4033 | else if (i != 0)
|
---|
4034 | fatal ("emxbind failed\n", NULL);
|
---|
4035 | if (chmod (exe_filename, filemode | (0111 & ~mask)) == -1)
|
---|
4036 | perror_name (exe_filename);
|
---|
4037 | if (touch_filename != NULL)
|
---|
4038 | {
|
---|
4039 | char execname[512];
|
---|
4040 | _execname(execname, sizeof (execname));
|
---|
4041 | strcpy(_getname(execname), "ldstub.bin");
|
---|
4042 | /* Copy stub into file */
|
---|
4043 | if (DosCopy(execname, touch_filename, 4))
|
---|
4044 | {
|
---|
4045 | errno = EACCES;
|
---|
4046 | perror_name (execname);
|
---|
4047 | }
|
---|
4048 | /* Now touch it */
|
---|
4049 | if (utime(touch_filename, NULL))
|
---|
4050 | perror_name (touch_filename);
|
---|
4051 | }
|
---|
4052 | while (j-- > 0)
|
---|
4053 | FREEA (freeav[j]);
|
---|
4054 | }
|
---|
4055 | else if (exe_filename != NULL) /* RSXNT */
|
---|
4056 | {
|
---|
4057 | char *nargv[10];
|
---|
4058 | char *freea = NULL;
|
---|
4059 | int i, saved_errno;
|
---|
4060 |
|
---|
4061 | i = 0;
|
---|
4062 | nargv[i++] = "ntbind";
|
---|
4063 | nargv[i++] = output_filename;
|
---|
4064 | nargv[i++] = "-o";
|
---|
4065 | nargv[i++] = exe_filename;
|
---|
4066 | nargv[i++] = "-s";
|
---|
4067 | if (rsxnt_linked == RSXNT_WIN32)
|
---|
4068 | nargv[i++] = (emxbind_strip) ? "dosstub.dos" : "dosstub.dbg";
|
---|
4069 | else
|
---|
4070 | {
|
---|
4071 | nargv[i++] = "dosstub.rsx";
|
---|
4072 | if (emxbind_strip)
|
---|
4073 | nargv[i++] = "-strip";
|
---|
4074 | }
|
---|
4075 | if (def_filename != NULL)
|
---|
4076 | {
|
---|
4077 | nargv[i++] = "-d";
|
---|
4078 | freea = nargv[i] = ALLOCA (strlen (def_filename) + 3);
|
---|
4079 | strcpy(nargv[i], def_filename);
|
---|
4080 | i++;
|
---|
4081 | }
|
---|
4082 | nargv[i] = NULL;
|
---|
4083 |
|
---|
4084 | i = spawnvp (P_WAIT, "ntbind", nargv);
|
---|
4085 | saved_errno = errno; unlink (output_filename); errno = saved_errno;
|
---|
4086 | if (i < 0)
|
---|
4087 | perror_name ("ntbind");
|
---|
4088 | else if (i != 0)
|
---|
4089 | fatal ("ntbind failed\n", NULL);
|
---|
4090 | if (chmod (exe_filename, filemode | (0111 & ~mask)) == -1)
|
---|
4091 | perror_name (exe_filename);
|
---|
4092 | if (touch_filename != NULL)
|
---|
4093 | {
|
---|
4094 | i = open (touch_filename,
|
---|
4095 | O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
|
---|
4096 | if (i < 0)
|
---|
4097 | perror_name (touch_filename);
|
---|
4098 | close (i);
|
---|
4099 | }
|
---|
4100 | FREEA (freea);
|
---|
4101 | }
|
---|
4102 | }
|
---|
4103 | |
---|
4104 |
|
---|
4105 | void copy_text (struct file_entry *entry);
|
---|
4106 | void copy_data (struct file_entry *entry);
|
---|
4107 | void perform_relocation ( char *data, int pc_relocation, int data_size,
|
---|
4108 | struct relocation_info *reloc_info, int reloc_size, struct file_entry *entry);
|
---|
4109 | #ifdef DEBUG_BIRD
|
---|
4110 | void dbg_dump_rel(struct file_entry *entry, struct relocation_info * rel,
|
---|
4111 | size_t reloc_size, const char *desc);
|
---|
4112 | #endif
|
---|
4113 |
|
---|
4114 | /* Relocate the text segment of each input file
|
---|
4115 | and write to the output file. */
|
---|
4116 |
|
---|
4117 | void
|
---|
4118 | write_text ()
|
---|
4119 | {
|
---|
4120 | if (trace_files)
|
---|
4121 | fprintf (stderr, "Copying and relocating text:\n\n");
|
---|
4122 |
|
---|
4123 | lseek (outdesc, output_text_offset + text_header_size, 0);
|
---|
4124 |
|
---|
4125 | each_full_file (copy_text, 0);
|
---|
4126 | file_close ();
|
---|
4127 |
|
---|
4128 | if (trace_files)
|
---|
4129 | fprintf (stderr, "\n");
|
---|
4130 |
|
---|
4131 | padfile (text_pad, outdesc);
|
---|
4132 | }
|
---|
4133 |
|
---|
4134 | /* Read in all of the relocation information */
|
---|
4135 |
|
---|
4136 | void
|
---|
4137 | read_relocation (void)
|
---|
4138 | {
|
---|
4139 | each_full_file (read_file_relocation, 0);
|
---|
4140 | }
|
---|
4141 |
|
---|
4142 | /* Read in the relocation sections of ENTRY if necessary */
|
---|
4143 |
|
---|
4144 | void
|
---|
4145 | read_file_relocation (entry)
|
---|
4146 | struct file_entry *entry;
|
---|
4147 | {
|
---|
4148 | register struct relocation_info *reloc;
|
---|
4149 | int desc;
|
---|
4150 | int read_return;
|
---|
4151 |
|
---|
4152 | desc = -1;
|
---|
4153 | if (!entry->textrel)
|
---|
4154 | {
|
---|
4155 | reloc = (struct relocation_info *) xmalloc (entry->text_reloc_size);
|
---|
4156 | desc = file_open (entry);
|
---|
4157 | lseek (desc, entry->starting_offset + entry->text_reloc_offset, L_SET);
|
---|
4158 | if (entry->text_reloc_size != (read_return = read (desc, reloc, entry->text_reloc_size)))
|
---|
4159 | {
|
---|
4160 | fprintf (stderr, "Return from read: %d\n", read_return);
|
---|
4161 | fatal_with_file ("premature eof in text relocation of ", entry);
|
---|
4162 | }
|
---|
4163 | entry->textrel = reloc;
|
---|
4164 | }
|
---|
4165 |
|
---|
4166 | if (!entry->datarel)
|
---|
4167 | {
|
---|
4168 | reloc = (struct relocation_info *) xmalloc (entry->data_reloc_size);
|
---|
4169 | if (desc == -1) desc = file_open (entry);
|
---|
4170 | lseek (desc, entry->starting_offset + entry->data_reloc_offset, L_SET);
|
---|
4171 | if (entry->data_reloc_size != read (desc, reloc, entry->data_reloc_size))
|
---|
4172 | fatal_with_file ("premature eof in data relocation of ", entry);
|
---|
4173 | entry->datarel = reloc;
|
---|
4174 | }
|
---|
4175 | #ifdef DEBUG_BIRD
|
---|
4176 | dbg_dump_rel(entry, entry->textrel, entry->text_reloc_size, "text");
|
---|
4177 | dbg_dump_rel(entry, entry->datarel, entry->data_reloc_size, "data");
|
---|
4178 | #endif
|
---|
4179 | }
|
---|
4180 |
|
---|
4181 | /* Read the text segment contents of ENTRY, relocate them,
|
---|
4182 | and write the result to the output file.
|
---|
4183 | If `-r', save the text relocation for later reuse. */
|
---|
4184 |
|
---|
4185 | void
|
---|
4186 | copy_text (entry)
|
---|
4187 | struct file_entry *entry;
|
---|
4188 | {
|
---|
4189 | register char *bytes;
|
---|
4190 | register int desc;
|
---|
4191 | register struct relocation_info *reloc;
|
---|
4192 | int free_reloc = 0;
|
---|
4193 |
|
---|
4194 | if (trace_files)
|
---|
4195 | prline_file_name (entry, stderr);
|
---|
4196 |
|
---|
4197 | desc = file_open (entry);
|
---|
4198 |
|
---|
4199 | /* Allocate space for the file's text section */
|
---|
4200 |
|
---|
4201 | bytes = (char *) ALLOCA (entry->text_size);
|
---|
4202 |
|
---|
4203 | /* Deal with relocation information however is appropriate */
|
---|
4204 |
|
---|
4205 | if (entry->textrel) reloc = entry->textrel;
|
---|
4206 | else if (output_style == OUTPUT_RELOCATABLE || reloc_flag)
|
---|
4207 | {
|
---|
4208 | read_file_relocation (entry);
|
---|
4209 | reloc = entry->textrel;
|
---|
4210 | }
|
---|
4211 | else
|
---|
4212 | {
|
---|
4213 | free_reloc = 1;
|
---|
4214 | reloc = (struct relocation_info *) ALLOCA (entry->text_reloc_size);
|
---|
4215 | lseek (desc, entry->starting_offset + entry->text_reloc_offset, L_SET);
|
---|
4216 | if (entry->text_reloc_size != read (desc, reloc, entry->text_reloc_size))
|
---|
4217 | fatal_with_file ("premature eof in text relocation of ", entry);
|
---|
4218 | }
|
---|
4219 |
|
---|
4220 | /* Read the text section into core. */
|
---|
4221 |
|
---|
4222 | lseek (desc, entry->starting_offset + entry->text_offset, L_SET);
|
---|
4223 | if (entry->text_size != read (desc, bytes, entry->text_size))
|
---|
4224 | fatal_with_file ("premature eof in text section of ", entry);
|
---|
4225 |
|
---|
4226 | /* Relocate the text according to the text relocation. */
|
---|
4227 |
|
---|
4228 | perform_relocation (bytes, entry->text_start_address - entry->orig_text_address,
|
---|
4229 | entry->text_size, reloc, entry->text_reloc_size, entry);
|
---|
4230 |
|
---|
4231 | /* Write the relocated text to the output file. */
|
---|
4232 |
|
---|
4233 | mywrite (bytes, 1, entry->text_size, outdesc);
|
---|
4234 |
|
---|
4235 | FREEA (bytes);
|
---|
4236 | if (free_reloc)
|
---|
4237 | FREEA (reloc);
|
---|
4238 | }
|
---|
4239 |
|
---|
4240 | #ifdef DEBUG_BIRD
|
---|
4241 | void dbg_dump_rel(struct file_entry *entry, struct relocation_info * rel,
|
---|
4242 | size_t reloc_size, const char *desc)
|
---|
4243 | {
|
---|
4244 | struct relocation_info *relend = (struct relocation_info *)((char*)rel + reloc_size);
|
---|
4245 | int i;
|
---|
4246 |
|
---|
4247 | fprintf(stderr,
|
---|
4248 | "dbg: %s relocations %s:\n"
|
---|
4249 | "dbg: rel - Address len sym# attrs\n",
|
---|
4250 | desc, entry->filename);
|
---|
4251 | i = 0;
|
---|
4252 | while (rel < relend)
|
---|
4253 | {
|
---|
4254 | fprintf(stderr, "dbg: %3d - %08x 2^%d %06x %s%s",
|
---|
4255 | i,
|
---|
4256 | rel->r_address,
|
---|
4257 | rel->r_length,
|
---|
4258 | rel->r_symbolnum,
|
---|
4259 | rel->r_extern ? "Extrn " : " ",
|
---|
4260 | rel->r_pcrel ? "PCRel " : " "
|
---|
4261 | );
|
---|
4262 | if (rel->r_extern)
|
---|
4263 | { /* find the symbol. */
|
---|
4264 | struct nlist *s = &entry->symbols[rel->r_symbolnum];
|
---|
4265 | fprintf(stderr, " s.val:%08lx s.typ:%02x s.des:%04x s.oth:%02x",
|
---|
4266 | s->n_value,
|
---|
4267 | (unsigned)s->n_type,
|
---|
4268 | s->n_desc,
|
---|
4269 | (unsigned)s->n_other);
|
---|
4270 | if (s->n_un.n_strx < 0x20000)
|
---|
4271 | fprintf(stderr, " !!bad symbol ptr %p", s->n_un.n_name);
|
---|
4272 | else
|
---|
4273 | {
|
---|
4274 | struct glosym *sym = (struct glosym *)s->n_un.n_name;
|
---|
4275 | fprintf(stderr, " %s", sym->name);
|
---|
4276 | }
|
---|
4277 | }
|
---|
4278 | fprintf(stderr, "\n");
|
---|
4279 | /* next */
|
---|
4280 | i++;
|
---|
4281 | rel++;
|
---|
4282 | }
|
---|
4283 | }
|
---|
4284 | #endif
|
---|
4285 | |
---|
4286 |
|
---|
4287 | /* Relocate the data segment of each input file
|
---|
4288 | and write to the output file. */
|
---|
4289 |
|
---|
4290 | void
|
---|
4291 | write_data ()
|
---|
4292 | {
|
---|
4293 | if (trace_files)
|
---|
4294 | fprintf (stderr, "Copying and relocating data:\n\n");
|
---|
4295 |
|
---|
4296 | lseek (outdesc, output_data_offset, 0);
|
---|
4297 |
|
---|
4298 | each_full_file (copy_data, 0);
|
---|
4299 | file_close ();
|
---|
4300 |
|
---|
4301 | /* Write out the set element vectors. See digest symbols for
|
---|
4302 | description of length of the set vector section. */
|
---|
4303 |
|
---|
4304 | padfile (set_sect_pad, outdesc);
|
---|
4305 |
|
---|
4306 | if (set_vector_count)
|
---|
4307 | mywrite (set_vectors, set_symbol_count + 2 * set_vector_count,
|
---|
4308 | sizeof (unsigned long), outdesc);
|
---|
4309 |
|
---|
4310 | if (trace_files)
|
---|
4311 | fprintf (stderr, "\n");
|
---|
4312 |
|
---|
4313 | padfile (data_pad, outdesc);
|
---|
4314 | }
|
---|
4315 |
|
---|
4316 | /* Read the data segment contents of ENTRY, relocate them,
|
---|
4317 | and write the result to the output file.
|
---|
4318 | If `-r', save the data relocation for later reuse.
|
---|
4319 | See comments in `copy_text'. */
|
---|
4320 |
|
---|
4321 | void
|
---|
4322 | copy_data (entry)
|
---|
4323 | struct file_entry *entry;
|
---|
4324 | {
|
---|
4325 | register struct relocation_info *reloc;
|
---|
4326 | register char *bytes;
|
---|
4327 | register int desc;
|
---|
4328 | int free_reloc = 0;
|
---|
4329 |
|
---|
4330 | if (trace_files)
|
---|
4331 | prline_file_name (entry, stderr);
|
---|
4332 |
|
---|
4333 | desc = file_open (entry);
|
---|
4334 |
|
---|
4335 | bytes = (char *) ALLOCA (entry->data_size);
|
---|
4336 |
|
---|
4337 | if (entry->datarel) reloc = entry->datarel;
|
---|
4338 | else if (output_style == OUTPUT_RELOCATABLE || reloc_flag) /* Will need this again */
|
---|
4339 | {
|
---|
4340 | read_file_relocation (entry);
|
---|
4341 | reloc = entry->datarel;
|
---|
4342 | }
|
---|
4343 | else
|
---|
4344 | {
|
---|
4345 | free_reloc = 1;
|
---|
4346 | reloc = (struct relocation_info *) ALLOCA (entry->data_reloc_size);
|
---|
4347 | lseek (desc, entry->starting_offset + entry->data_reloc_offset, L_SET);
|
---|
4348 | if (entry->data_reloc_size != read (desc, reloc, entry->data_reloc_size))
|
---|
4349 | fatal_with_file ("premature eof in data relocation of ", entry);
|
---|
4350 | }
|
---|
4351 |
|
---|
4352 | lseek (desc, entry->starting_offset + entry->data_offset, L_SET);
|
---|
4353 | if (entry->data_size != read (desc, bytes, entry->data_size))
|
---|
4354 | fatal_with_file ("premature eof in data section of ", entry);
|
---|
4355 |
|
---|
4356 | perform_relocation (bytes, entry->data_start_address - entry->orig_data_address,
|
---|
4357 | entry->data_size, reloc, entry->data_reloc_size, entry);
|
---|
4358 |
|
---|
4359 | mywrite (bytes, 1, entry->data_size, outdesc);
|
---|
4360 | padfile ((SECTION_ALIGN - entry->data_size) & SECTION_ALIGN_MASK, outdesc);
|
---|
4361 |
|
---|
4362 | FREEA (bytes);
|
---|
4363 | if (free_reloc)
|
---|
4364 | FREEA (reloc);
|
---|
4365 | }
|
---|
4366 | |
---|
4367 |
|
---|
4368 | /* Relocate ENTRY's text or data section contents.
|
---|
4369 | DATA is the address of the contents, in core.
|
---|
4370 | DATA_SIZE is the length of the contents.
|
---|
4371 | PC_RELOCATION is the difference between the address of the contents
|
---|
4372 | in the output file and its address in the input file.
|
---|
4373 | RELOC_INFO is the address of the relocation info, in core.
|
---|
4374 | RELOC_SIZE is its length in bytes. */
|
---|
4375 | /* This version is about to be severly hacked by Randy. Hope it
|
---|
4376 | works afterwards. */
|
---|
4377 | void
|
---|
4378 | perform_relocation (data, pc_relocation, data_size, reloc_info, reloc_size, entry)
|
---|
4379 | char *data;
|
---|
4380 | struct relocation_info *reloc_info;
|
---|
4381 | struct file_entry *entry;
|
---|
4382 | int pc_relocation;
|
---|
4383 | int data_size;
|
---|
4384 | int reloc_size;
|
---|
4385 | {
|
---|
4386 | register struct relocation_info *p = reloc_info;
|
---|
4387 | struct relocation_info *end
|
---|
4388 | = reloc_info + reloc_size / sizeof (struct relocation_info);
|
---|
4389 | int text_relocation = entry->text_start_address - entry->orig_text_address;
|
---|
4390 | int data_relocation = entry->data_start_address - entry->orig_data_address;
|
---|
4391 | int bss_relocation = entry->bss_start_address - entry->orig_bss_address;
|
---|
4392 |
|
---|
4393 | for (; p < end; p++)
|
---|
4394 | {
|
---|
4395 | register int relocation = 0;
|
---|
4396 | register int addr = RELOC_ADDRESS(p);
|
---|
4397 | register unsigned int mask = 0;
|
---|
4398 |
|
---|
4399 | if (addr >= data_size)
|
---|
4400 | fatal_with_file ("relocation address out of range in ", entry);
|
---|
4401 |
|
---|
4402 | if (RELOC_EXTERN_P(p))
|
---|
4403 | {
|
---|
4404 | int symindex = RELOC_SYMBOL (p) * sizeof (struct nlist);
|
---|
4405 | symbol *sp = ((symbol *)
|
---|
4406 | (((struct nlist *)
|
---|
4407 | (((char *)entry->symbols) + symindex))
|
---|
4408 | ->n_un.n_name));
|
---|
4409 |
|
---|
4410 | #ifdef N_INDR
|
---|
4411 | /* Resolve indirection */
|
---|
4412 | if ((sp->defined & ~N_EXT) == N_INDR)
|
---|
4413 | sp = (symbol *) sp->value;
|
---|
4414 | #endif
|
---|
4415 |
|
---|
4416 | if (symindex >= entry->syms_size)
|
---|
4417 | fatal_with_file ("relocation symbolnum out of range in ", entry);
|
---|
4418 |
|
---|
4419 | /* If the symbol is undefined, leave it at zero. */
|
---|
4420 | if (! sp->defined)
|
---|
4421 | relocation = 0;
|
---|
4422 | else
|
---|
4423 | relocation = sp->value;
|
---|
4424 | }
|
---|
4425 | else switch (RELOC_TYPE(p))
|
---|
4426 | {
|
---|
4427 | case N_TEXT:
|
---|
4428 | case N_TEXT | N_EXT:
|
---|
4429 | relocation = text_relocation;
|
---|
4430 | break;
|
---|
4431 |
|
---|
4432 | case N_DATA:
|
---|
4433 | case N_DATA | N_EXT:
|
---|
4434 | relocation = data_relocation;
|
---|
4435 | break;
|
---|
4436 |
|
---|
4437 | case N_BSS:
|
---|
4438 | case N_BSS | N_EXT:
|
---|
4439 | relocation = bss_relocation;
|
---|
4440 | break;
|
---|
4441 |
|
---|
4442 | case N_ABS:
|
---|
4443 | case N_ABS | N_EXT:
|
---|
4444 | /* Don't know why this code would occur, but apparently it does. */
|
---|
4445 | break;
|
---|
4446 |
|
---|
4447 | default:
|
---|
4448 | fatal_with_file ("nonexternal relocation code invalid in ", entry);
|
---|
4449 | }
|
---|
4450 |
|
---|
4451 | if (RELOC_PCREL_P(p))
|
---|
4452 | relocation -= pc_relocation;
|
---|
4453 |
|
---|
4454 | #ifdef RELOC_ADD_EXTRA
|
---|
4455 | relocation += RELOC_ADD_EXTRA(p);
|
---|
4456 | if (output_style == OUTPUT_RELOCATABLE)
|
---|
4457 | {
|
---|
4458 | /* If this RELOC_ADD_EXTRA is 0, it means that the
|
---|
4459 | symbol was external and the relocation does not
|
---|
4460 | need a fixup here. */
|
---|
4461 | if (RELOC_ADD_EXTRA (p))
|
---|
4462 | {
|
---|
4463 | if (! RELOC_PCREL_P (p))
|
---|
4464 | RELOC_ADD_EXTRA (p) = relocation;
|
---|
4465 | else
|
---|
4466 | RELOC_ADD_EXTRA (p) -= pc_relocation;
|
---|
4467 | }
|
---|
4468 | #if 0
|
---|
4469 | if (! RELOC_PCREL_P (p))
|
---|
4470 | {
|
---|
4471 | if ((int)p->r_type <= RELOC_32
|
---|
4472 | || RELOC_EXTERN_P (p) == 0)
|
---|
4473 | RELOC_ADD_EXTRA (p) = relocation;
|
---|
4474 | }
|
---|
4475 | else if (RELOC_EXTERN_P (p))
|
---|
4476 | RELOC_ADD_EXTRA (p) -= pc_relocation;
|
---|
4477 | #endif
|
---|
4478 | continue;
|
---|
4479 | }
|
---|
4480 | #endif
|
---|
4481 |
|
---|
4482 | relocation >>= RELOC_VALUE_RIGHTSHIFT(p);
|
---|
4483 |
|
---|
4484 | /* Unshifted mask for relocation */
|
---|
4485 | mask = (1 << RELOC_TARGET_BITSIZE(p)) - 1;
|
---|
4486 | relocation &= mask;
|
---|
4487 |
|
---|
4488 | /* Shift everything up to where it's going to be used */
|
---|
4489 | relocation <<= RELOC_TARGET_BITPOS(p);
|
---|
4490 | mask <<= RELOC_TARGET_BITPOS(p);
|
---|
4491 |
|
---|
4492 | switch (RELOC_TARGET_SIZE(p))
|
---|
4493 | {
|
---|
4494 | case 0:
|
---|
4495 | if (RELOC_MEMORY_SUB_P(p))
|
---|
4496 | relocation -= mask & *(char *) (data + addr);
|
---|
4497 | else if (RELOC_MEMORY_ADD_P(p))
|
---|
4498 | relocation += mask & *(char *) (data + addr);
|
---|
4499 | *(char *) (data + addr) &= ~mask;
|
---|
4500 | *(char *) (data + addr) |= relocation;
|
---|
4501 | break;
|
---|
4502 |
|
---|
4503 | case 1:
|
---|
4504 | if (RELOC_MEMORY_SUB_P(p))
|
---|
4505 | relocation -= mask & *(short *) (data + addr);
|
---|
4506 | else if (RELOC_MEMORY_ADD_P(p))
|
---|
4507 | relocation += mask & *(short *) (data + addr);
|
---|
4508 | *(short *) (data + addr) &= ~mask;
|
---|
4509 | *(short *) (data + addr) |= relocation;
|
---|
4510 | break;
|
---|
4511 |
|
---|
4512 | case 2:
|
---|
4513 | #ifdef CROSS_LINKER
|
---|
4514 | /* This is necessary if the host has stricter alignment
|
---|
4515 | than the target. Too slow to use all the time.
|
---|
4516 | Also doesn't deal with differing byte-order. */
|
---|
4517 | {
|
---|
4518 | /* Thing to relocate. */
|
---|
4519 | long thing;
|
---|
4520 | bcopy (data + addr, &thing, sizeof (thing));
|
---|
4521 | if (RELOC_MEMORY_SUB_P (p))
|
---|
4522 | relocation -= mask & thing;
|
---|
4523 | else if (RELOC_MEMORY_ADD_P (p))
|
---|
4524 | relocation += mask & thing;
|
---|
4525 | thing = (thing & ~mask) | relocation;
|
---|
4526 | bcopy (&thing, data + addr, sizeof (thing));
|
---|
4527 | }
|
---|
4528 | #else /* not CROSS_LINKER */
|
---|
4529 | if (RELOC_MEMORY_SUB_P(p))
|
---|
4530 | relocation -= mask & *(long *) (data + addr);
|
---|
4531 | else if (RELOC_MEMORY_ADD_P(p))
|
---|
4532 | relocation += mask & *(long *) (data + addr);
|
---|
4533 | *(long *) (data + addr) &= ~mask;
|
---|
4534 | *(long *) (data + addr) |= relocation;
|
---|
4535 | #endif /* not CROSS_LINKER */
|
---|
4536 | break;
|
---|
4537 |
|
---|
4538 | default:
|
---|
4539 | fatal_with_file ("Unimplemented relocation field length in ", entry);
|
---|
4540 | }
|
---|
4541 | }
|
---|
4542 | }
|
---|
4543 | |
---|
4544 |
|
---|
4545 | /* For OUTPUT_RELOCATABLE only: write out the relocation,
|
---|
4546 | relocating the addresses-to-be-relocated. */
|
---|
4547 |
|
---|
4548 | void coptxtrel (struct file_entry *entry);
|
---|
4549 | void copdatrel (struct file_entry *entry);
|
---|
4550 |
|
---|
4551 | void
|
---|
4552 | write_rel ()
|
---|
4553 | {
|
---|
4554 | register int i;
|
---|
4555 | register int count = 0;
|
---|
4556 |
|
---|
4557 | if (trace_files)
|
---|
4558 | fprintf (stderr, "Writing text relocation:\n\n");
|
---|
4559 |
|
---|
4560 | /* Assign each global symbol a sequence number, giving the order
|
---|
4561 | in which `write_syms' will write it.
|
---|
4562 | This is so we can store the proper symbolnum fields
|
---|
4563 | in relocation entries we write. */
|
---|
4564 |
|
---|
4565 | for (i = 0; i < TABSIZE; i++)
|
---|
4566 | {
|
---|
4567 | symbol *sp;
|
---|
4568 | for (sp = symtab[i]; sp; sp = sp->link)
|
---|
4569 | if (sp->referenced || sp->defined)
|
---|
4570 | {
|
---|
4571 | sp->def_count = count++;
|
---|
4572 | /* Leave room for the reference required by N_INDR, if
|
---|
4573 | necessary. */
|
---|
4574 | if ((sp->defined & ~N_EXT) == N_INDR)
|
---|
4575 | if (!reloc_flag)
|
---|
4576 | count++;
|
---|
4577 | }
|
---|
4578 | }
|
---|
4579 | /* Correct, because if (OUTPUT_RELOCATABLE), we will also be writing
|
---|
4580 | whatever indirect blocks we have. */
|
---|
4581 | if (count != defined_global_sym_count
|
---|
4582 | + undefined_global_sym_count + global_indirect_count)
|
---|
4583 | fatal ("internal error");
|
---|
4584 |
|
---|
4585 | /* Write out the relocations of all files, remembered from copy_text. */
|
---|
4586 |
|
---|
4587 | lseek (outdesc, output_trel_offset, 0);
|
---|
4588 | each_full_file (coptxtrel, 0);
|
---|
4589 |
|
---|
4590 | if (trace_files)
|
---|
4591 | fprintf (stderr, "\nWriting data relocation:\n\n");
|
---|
4592 |
|
---|
4593 | lseek (outdesc, output_drel_offset, 0);
|
---|
4594 | each_full_file (copdatrel, 0);
|
---|
4595 | if (reloc_flag)
|
---|
4596 | {
|
---|
4597 | int i;
|
---|
4598 | int n = set_sect_size / sizeof (unsigned long);
|
---|
4599 | struct relocation_info reloc;
|
---|
4600 |
|
---|
4601 | memset (&reloc, 0, sizeof (reloc));
|
---|
4602 | RELOC_PCREL_P (&reloc) = 0;
|
---|
4603 | RELOC_TARGET_SIZE (&reloc) = 2;
|
---|
4604 | RELOC_EXTERN_P (&reloc) = 0;
|
---|
4605 | for (i = 0; i < n; ++i)
|
---|
4606 | switch (set_reloc[i] & ~N_EXT)
|
---|
4607 | {
|
---|
4608 | case N_TEXT:
|
---|
4609 | case N_DATA:
|
---|
4610 | RELOC_SYMBOL (&reloc) = set_reloc[i] & ~N_EXT;
|
---|
4611 | RELOC_ADDRESS (&reloc)
|
---|
4612 | = set_sect_start + i * sizeof (unsigned long) - data_start;
|
---|
4613 | mywrite (&reloc, sizeof (reloc), 1, outdesc);
|
---|
4614 | break;
|
---|
4615 | case N_ABS:
|
---|
4616 | break;
|
---|
4617 | default:
|
---|
4618 | fatal ("N_SETB not supported", (char *)0);
|
---|
4619 | }
|
---|
4620 | }
|
---|
4621 |
|
---|
4622 | if (trace_files)
|
---|
4623 | fprintf (stderr, "\n");
|
---|
4624 | }
|
---|
4625 |
|
---|
4626 | void
|
---|
4627 | coptxtrel (entry)
|
---|
4628 | struct file_entry *entry;
|
---|
4629 | {
|
---|
4630 | register struct relocation_info *p, *end;
|
---|
4631 | register int reloc = entry->text_start_address - text_start;
|
---|
4632 |
|
---|
4633 | p = entry->textrel;
|
---|
4634 | end = (struct relocation_info *) (entry->text_reloc_size + (char *) p);
|
---|
4635 | while (p < end)
|
---|
4636 | {
|
---|
4637 | RELOC_ADDRESS(p) += reloc;
|
---|
4638 | if (RELOC_EXTERN_P(p))
|
---|
4639 | {
|
---|
4640 | register int symindex = RELOC_SYMBOL(p) * sizeof (struct nlist);
|
---|
4641 | symbol *symptr = ((symbol *)
|
---|
4642 | (((struct nlist *)
|
---|
4643 | (((char *)entry->symbols) + symindex))
|
---|
4644 | ->n_un.n_name));
|
---|
4645 |
|
---|
4646 | if (symindex >= entry->syms_size)
|
---|
4647 | fatal_with_file ("relocation symbolnum out of range in ", entry);
|
---|
4648 |
|
---|
4649 | #ifdef N_INDR
|
---|
4650 | /* Resolve indirection. */
|
---|
4651 | if ((symptr->defined & ~N_EXT) == N_INDR)
|
---|
4652 | symptr = (symbol *) symptr->value;
|
---|
4653 | #endif
|
---|
4654 |
|
---|
4655 | /* If the symbol is now defined, change the external relocation
|
---|
4656 | to an internal one. */
|
---|
4657 |
|
---|
4658 | if (symptr->defined && symptr->defined != (N_IMP1 | N_EXT))
|
---|
4659 | {
|
---|
4660 | RELOC_EXTERN_P(p) = 0;
|
---|
4661 | RELOC_SYMBOL(p) = (symptr->defined & ~N_EXT);
|
---|
4662 | if (RELOC_SYMBOL (p) == N_SETV)
|
---|
4663 | RELOC_SYMBOL (p) = N_DATA;
|
---|
4664 | #ifdef RELOC_ADD_EXTRA
|
---|
4665 | /* If we aren't going to be adding in the value in
|
---|
4666 | memory on the next pass of the loader, then we need
|
---|
4667 | to add it in from the relocation entry. Otherwise
|
---|
4668 | the work we did in this pass is lost. */
|
---|
4669 | if (!RELOC_MEMORY_ADD_P(p))
|
---|
4670 | RELOC_ADD_EXTRA (p) += symptr->value;
|
---|
4671 | #endif
|
---|
4672 | }
|
---|
4673 | else
|
---|
4674 | /* Debugger symbols come first, so have to start this
|
---|
4675 | after them. */
|
---|
4676 | RELOC_SYMBOL(p) = (symptr->def_count + nsyms
|
---|
4677 | - defined_global_sym_count
|
---|
4678 | - undefined_global_sym_count
|
---|
4679 | - global_indirect_count);
|
---|
4680 | }
|
---|
4681 | p++;
|
---|
4682 | }
|
---|
4683 |
|
---|
4684 | mywrite (entry->textrel, 1, entry->text_reloc_size, outdesc);
|
---|
4685 | }
|
---|
4686 |
|
---|
4687 | void
|
---|
4688 | copdatrel (entry)
|
---|
4689 | struct file_entry *entry;
|
---|
4690 | {
|
---|
4691 | register struct relocation_info *p, *end;
|
---|
4692 | /* Relocate the address of the relocation.
|
---|
4693 | Old address is relative to start of the input file's data section.
|
---|
4694 | New address is relative to start of the output file's data section.
|
---|
4695 |
|
---|
4696 | So the amount we need to relocate it by is the offset of this
|
---|
4697 | input file's data section within the output file's data section. */
|
---|
4698 | register int reloc = entry->data_start_address - data_start;
|
---|
4699 |
|
---|
4700 | p = entry->datarel;
|
---|
4701 | end = (struct relocation_info *) (entry->data_reloc_size + (char *) p);
|
---|
4702 | while (p < end)
|
---|
4703 | {
|
---|
4704 | RELOC_ADDRESS(p) += reloc;
|
---|
4705 | if (RELOC_EXTERN_P(p))
|
---|
4706 | {
|
---|
4707 | register int symindex = RELOC_SYMBOL(p);
|
---|
4708 | symbol *symptr = (symbol *)(entry->symbols [symindex].n_un.n_name);
|
---|
4709 | int symtype;
|
---|
4710 |
|
---|
4711 | if (symindex >= (entry->syms_size / sizeof (struct nlist)))
|
---|
4712 | fatal_with_file ("relocation symbolnum out of range in ", entry);
|
---|
4713 |
|
---|
4714 | #ifdef N_INDR
|
---|
4715 | /* Resolve indirection. */
|
---|
4716 | if ((symptr->defined & ~N_EXT) == N_INDR)
|
---|
4717 | symptr = (symbol *) symptr->value;
|
---|
4718 | #endif
|
---|
4719 |
|
---|
4720 | symtype = symptr->defined & ~N_EXT;
|
---|
4721 |
|
---|
4722 | if (force_common_definition
|
---|
4723 | || (reloc_flag && symtype != N_IMP1)
|
---|
4724 | || symtype == N_DATA || symtype == N_TEXT
|
---|
4725 | || symtype == N_ABS || symtype == N_BSS)
|
---|
4726 | {
|
---|
4727 | if (symtype == N_SETV)
|
---|
4728 | symtype = N_DATA;
|
---|
4729 | RELOC_EXTERN_P(p) = 0;
|
---|
4730 | RELOC_SYMBOL(p) = symtype;
|
---|
4731 | }
|
---|
4732 | else
|
---|
4733 | /* Debugger symbols come first, so have to start this
|
---|
4734 | after them. */
|
---|
4735 | RELOC_SYMBOL(p) = (symptr->def_count
|
---|
4736 | + nsyms - defined_global_sym_count
|
---|
4737 | - undefined_global_sym_count
|
---|
4738 | - global_indirect_count);
|
---|
4739 |
|
---|
4740 | #if 0
|
---|
4741 | if ((symtype = symptr->defined) != (N_IMP1 | N_EXT))
|
---|
4742 | symtype = symptr->defined & ~N_EXT;
|
---|
4743 |
|
---|
4744 | if ((force_common_definition || reloc_flag)
|
---|
4745 | && (symtype != (N_IMP1 | N_EXT)))
|
---|
4746 | {
|
---|
4747 | if (force_common_definition
|
---|
4748 | || symtype == N_DATA || symtype == N_TEXT || symtype == N_ABS)
|
---|
4749 | {
|
---|
4750 | if (symtype == N_SETV)
|
---|
4751 | symtype = N_DATA;
|
---|
4752 | RELOC_EXTERN_P(p) = 0;
|
---|
4753 | RELOC_SYMBOL(p) = symtype;
|
---|
4754 | }
|
---|
4755 | else
|
---|
4756 | /* Debugger symbols come first, so have to start this
|
---|
4757 | after them. */
|
---|
4758 | RELOC_SYMBOL(p) = (symptr->def_count
|
---|
4759 | + nsyms - defined_global_sym_count
|
---|
4760 | - undefined_global_sym_count
|
---|
4761 | - global_indirect_count);
|
---|
4762 | }
|
---|
4763 | #endif
|
---|
4764 | }
|
---|
4765 | p++;
|
---|
4766 | }
|
---|
4767 |
|
---|
4768 | mywrite (entry->datarel, 1, entry->data_reloc_size, outdesc);
|
---|
4769 | }
|
---|
4770 | |
---|
4771 |
|
---|
4772 | void write_file_syms (struct file_entry *entry, int *syms_written_addr);
|
---|
4773 | void write_string_table (void);
|
---|
4774 |
|
---|
4775 | /* Total size of string table strings allocated so far,
|
---|
4776 | including strings in `strtab_vector'. */
|
---|
4777 | int strtab_size;
|
---|
4778 |
|
---|
4779 | /* Vector whose elements are strings to be added to the string table. */
|
---|
4780 | char **strtab_vector;
|
---|
4781 |
|
---|
4782 | /* Vector whose elements are the lengths of those strings. */
|
---|
4783 | int *strtab_lens;
|
---|
4784 |
|
---|
4785 | /* Index in `strtab_vector' at which the next string will be stored. */
|
---|
4786 | int strtab_index;
|
---|
4787 |
|
---|
4788 | /* Add the string NAME to the output file string table.
|
---|
4789 | Record it in `strtab_vector' to be output later.
|
---|
4790 | Return the index within the string table that this string will have. */
|
---|
4791 |
|
---|
4792 | int
|
---|
4793 | assign_string_table_index (name)
|
---|
4794 | char *name;
|
---|
4795 | {
|
---|
4796 | register int index = strtab_size;
|
---|
4797 | register int len = strlen (name) + 1;
|
---|
4798 |
|
---|
4799 | strtab_size += len;
|
---|
4800 | strtab_vector[strtab_index] = name;
|
---|
4801 | strtab_lens[strtab_index++] = len;
|
---|
4802 |
|
---|
4803 | return index;
|
---|
4804 | }
|
---|
4805 |
|
---|
4806 | FILE *outstream = (FILE *) 0;
|
---|
4807 |
|
---|
4808 | /* Write the contents of `strtab_vector' into the string table.
|
---|
4809 | This is done once for each file's local&debugger symbols
|
---|
4810 | and once for the global symbols. */
|
---|
4811 |
|
---|
4812 | void
|
---|
4813 | write_string_table (void)
|
---|
4814 | {
|
---|
4815 | register int i;
|
---|
4816 |
|
---|
4817 | lseek (outdesc, output_strs_offset + output_strs_size, 0);
|
---|
4818 |
|
---|
4819 | if (!outstream)
|
---|
4820 | outstream = fdopen (outdesc, "wb");
|
---|
4821 |
|
---|
4822 | for (i = 0; i < strtab_index; i++)
|
---|
4823 | {
|
---|
4824 | fwrite (strtab_vector[i], 1, strtab_lens[i], outstream);
|
---|
4825 | output_strs_size += strtab_lens[i];
|
---|
4826 | }
|
---|
4827 |
|
---|
4828 | fflush (outstream);
|
---|
4829 |
|
---|
4830 | /* Report I/O error such as disk full. */
|
---|
4831 | if (ferror (outstream))
|
---|
4832 | perror_name (output_filename);
|
---|
4833 | }
|
---|
4834 | |
---|
4835 |
|
---|
4836 | /* Write the symbol table and string table of the output file. */
|
---|
4837 |
|
---|
4838 | void
|
---|
4839 | write_syms ()
|
---|
4840 | {
|
---|
4841 | /* Number of symbols written so far. */
|
---|
4842 | int syms_written = 0;
|
---|
4843 | register int i;
|
---|
4844 | register symbol *sp;
|
---|
4845 |
|
---|
4846 | /* Buffer big enough for all the global symbols. One
|
---|
4847 | extra struct for each indirect symbol to hold the extra reference
|
---|
4848 | following. */
|
---|
4849 | struct nlist *buf = (struct nlist *) ALLOCA ((defined_global_sym_count
|
---|
4850 | + undefined_global_sym_count
|
---|
4851 | + global_indirect_count)
|
---|
4852 | * sizeof (struct nlist));
|
---|
4853 | /* Pointer for storing into BUF. */
|
---|
4854 | register struct nlist *bufp = buf;
|
---|
4855 |
|
---|
4856 | /* Size of string table includes the bytes that store the size. */
|
---|
4857 | strtab_size = sizeof strtab_size;
|
---|
4858 |
|
---|
4859 | output_syms_size = 0;
|
---|
4860 | output_strs_size = strtab_size;
|
---|
4861 |
|
---|
4862 | if (strip_symbols == STRIP_ALL)
|
---|
4863 | return;
|
---|
4864 |
|
---|
4865 | /* Write the local symbols defined by the various files. */
|
---|
4866 |
|
---|
4867 | each_file (write_file_syms, (int)&syms_written);
|
---|
4868 | file_close ();
|
---|
4869 |
|
---|
4870 | /* Now write out the global symbols. */
|
---|
4871 |
|
---|
4872 | /* Allocate two vectors that record the data to generate the string
|
---|
4873 | table from the global symbols written so far. This must include
|
---|
4874 | extra space for the references following indirect outputs. */
|
---|
4875 |
|
---|
4876 | strtab_vector = (char **) ALLOCA ((num_hash_tab_syms
|
---|
4877 | + global_indirect_count) * sizeof (char *));
|
---|
4878 | strtab_lens = (int *) ALLOCA ((num_hash_tab_syms
|
---|
4879 | + global_indirect_count) * sizeof (int));
|
---|
4880 | strtab_index = 0;
|
---|
4881 |
|
---|
4882 | /* Scan the symbol hash table, bucket by bucket. */
|
---|
4883 |
|
---|
4884 | for (i = 0; i < TABSIZE; i++)
|
---|
4885 | for (sp = symtab[i]; sp; sp = sp->link)
|
---|
4886 | {
|
---|
4887 | struct nlist nl;
|
---|
4888 |
|
---|
4889 | #ifdef N_SECT
|
---|
4890 | nl.n_sect = 0;
|
---|
4891 | #else
|
---|
4892 | nl.n_other = 0;
|
---|
4893 | #endif
|
---|
4894 | nl.n_desc = 0;
|
---|
4895 |
|
---|
4896 | /* Compute a `struct nlist' for the symbol. */
|
---|
4897 |
|
---|
4898 | if (sp->defined || sp->referenced)
|
---|
4899 | {
|
---|
4900 | /* common condition needs to be before undefined condition */
|
---|
4901 | /* because unallocated commons are set undefined in */
|
---|
4902 | /* digest_symbols */
|
---|
4903 | if (sp->defined > 1) /* defined with known type */
|
---|
4904 | {
|
---|
4905 | /* If the target of an indirect symbol has been
|
---|
4906 | defined and we are outputting an executable,
|
---|
4907 | resolve the indirection; it's no longer needed */
|
---|
4908 | if (output_style != OUTPUT_RELOCATABLE
|
---|
4909 | && ((sp->defined & ~N_EXT) == N_INDR)
|
---|
4910 | && (((symbol *) sp->value)->defined > 1))
|
---|
4911 | {
|
---|
4912 | symbol *newsp = (symbol *) sp->value;
|
---|
4913 | nl.n_type = newsp->defined;
|
---|
4914 | nl.n_value = newsp->value;
|
---|
4915 | }
|
---|
4916 | else
|
---|
4917 | {
|
---|
4918 | nl.n_type = sp->defined;
|
---|
4919 | if (sp->defined != (N_INDR | N_EXT))
|
---|
4920 | nl.n_value = sp->value;
|
---|
4921 | else
|
---|
4922 | nl.n_value = 0;
|
---|
4923 | }
|
---|
4924 | }
|
---|
4925 | else if (sp->max_common_size) /* defined as common but not allocated. */
|
---|
4926 | {
|
---|
4927 | /* happens only with -r and not -d */
|
---|
4928 | /* write out a common definition */
|
---|
4929 | nl.n_type = N_UNDF | N_EXT;
|
---|
4930 | nl.n_value = sp->max_common_size;
|
---|
4931 | }
|
---|
4932 | else if (!sp->defined && sp->weak)
|
---|
4933 | {
|
---|
4934 | nl.n_type = sp->weak;
|
---|
4935 | nl.n_value = 0;
|
---|
4936 | }
|
---|
4937 | else if (!sp->defined) /* undefined -- legit only if -r */
|
---|
4938 | {
|
---|
4939 | nl.n_type = N_UNDF | N_EXT;
|
---|
4940 | nl.n_value = 0;
|
---|
4941 | }
|
---|
4942 | else
|
---|
4943 | fatal ("internal error: %s defined in mysterious way", sp->name);
|
---|
4944 |
|
---|
4945 | /* Allocate string table space for the symbol name. */
|
---|
4946 |
|
---|
4947 | nl.n_un.n_strx = assign_string_table_index (sp->name);
|
---|
4948 |
|
---|
4949 | /* Output to the buffer and count it. */
|
---|
4950 |
|
---|
4951 | *bufp++ = nl;
|
---|
4952 | syms_written++;
|
---|
4953 | if (nl.n_type == (N_INDR | N_EXT))
|
---|
4954 | {
|
---|
4955 | struct nlist xtra_ref;
|
---|
4956 | xtra_ref.n_type = N_EXT | N_UNDF;
|
---|
4957 | xtra_ref.n_un.n_strx
|
---|
4958 | = assign_string_table_index (((symbol *) sp->value)->name);
|
---|
4959 | #ifdef N_SECT
|
---|
4960 | xtra_ref.n_sect = 0;
|
---|
4961 | #else
|
---|
4962 | xtra_ref.n_other = 0;
|
---|
4963 | #endif
|
---|
4964 | xtra_ref.n_desc = 0;
|
---|
4965 | xtra_ref.n_value = 0;
|
---|
4966 | *bufp++ = xtra_ref;
|
---|
4967 | syms_written++;
|
---|
4968 | }
|
---|
4969 | }
|
---|
4970 | }
|
---|
4971 |
|
---|
4972 | /* Output the buffer full of `struct nlist's. */
|
---|
4973 |
|
---|
4974 | lseek (outdesc, output_syms_offset + output_syms_size, 0);
|
---|
4975 | mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);
|
---|
4976 | output_syms_size += sizeof (struct nlist) * (bufp - buf);
|
---|
4977 |
|
---|
4978 | if (syms_written != nsyms)
|
---|
4979 | fatal ("internal error: wrong number of symbols written into output file", 0);
|
---|
4980 |
|
---|
4981 | /* Now the total string table size is known, so write it into the
|
---|
4982 | first word of the string table. */
|
---|
4983 |
|
---|
4984 | lseek (outdesc, output_strs_offset, 0);
|
---|
4985 | mywrite (&strtab_size, sizeof (int), 1, outdesc);
|
---|
4986 |
|
---|
4987 | /* Write the strings for the global symbols. */
|
---|
4988 |
|
---|
4989 | write_string_table ();
|
---|
4990 | FREEA (strtab_vector);
|
---|
4991 | FREEA (strtab_lens);
|
---|
4992 | FREEA (buf);
|
---|
4993 | }
|
---|
4994 | |
---|
4995 |
|
---|
4996 | /* Write the local and debugger symbols of file ENTRY.
|
---|
4997 | Increment *SYMS_WRITTEN_ADDR for each symbol that is written. */
|
---|
4998 |
|
---|
4999 | /* Note that we do not combine identical names of local symbols.
|
---|
5000 | dbx or gdb would be confused if we did that. */
|
---|
5001 |
|
---|
5002 | void
|
---|
5003 | write_file_syms (entry, syms_written_addr)
|
---|
5004 | struct file_entry *entry;
|
---|
5005 | int *syms_written_addr;
|
---|
5006 | {
|
---|
5007 | register struct nlist *p = entry->symbols;
|
---|
5008 | register struct nlist *end = p + entry->syms_size / sizeof (struct nlist);
|
---|
5009 |
|
---|
5010 | /* Buffer to accumulate all the syms before writing them.
|
---|
5011 | It has one extra slot for the local symbol we generate here. */
|
---|
5012 | struct nlist *buf
|
---|
5013 | = (struct nlist *) ALLOCA (entry->syms_size + sizeof (struct nlist));
|
---|
5014 | register struct nlist *bufp = buf;
|
---|
5015 |
|
---|
5016 | /* Upper bound on number of syms to be written here. */
|
---|
5017 | int max_syms = (entry->syms_size / sizeof (struct nlist)) + 1;
|
---|
5018 |
|
---|
5019 | /* Make tables that record, for each symbol, its name and its name's length.
|
---|
5020 | The elements are filled in by `assign_string_table_index'. */
|
---|
5021 |
|
---|
5022 | strtab_vector = (char **) ALLOCA (max_syms * sizeof (char *));
|
---|
5023 | strtab_lens = (int *) ALLOCA (max_syms * sizeof (int));
|
---|
5024 | strtab_index = 0;
|
---|
5025 |
|
---|
5026 | /* Generate a local symbol for the start of this file's text. */
|
---|
5027 |
|
---|
5028 | if (discard_locals != DISCARD_ALL)
|
---|
5029 | {
|
---|
5030 | struct nlist nl;
|
---|
5031 |
|
---|
5032 | nl.n_type = N_TEXT;
|
---|
5033 | #ifdef EMX /* fix GCC/ld/GDB problem */
|
---|
5034 | {
|
---|
5035 | char *tmp;
|
---|
5036 | int len;
|
---|
5037 |
|
---|
5038 | tmp = entry->local_sym_name;
|
---|
5039 | len = strlen (tmp);
|
---|
5040 | if (strncmp (tmp, "-l", 2) != 0
|
---|
5041 | && (len < 2 || strcmp (tmp+len-2, ".o") != 0))
|
---|
5042 | tmp = concat (tmp, ".o", NULL); /* Needed by GDB */
|
---|
5043 | nl.n_un.n_strx = assign_string_table_index (tmp);
|
---|
5044 | }
|
---|
5045 | #else /* !EMX */
|
---|
5046 | nl.n_un.n_strx = assign_string_table_index (entry->local_sym_name);
|
---|
5047 | #endif /* !EMX */
|
---|
5048 | nl.n_value = entry->text_start_address;
|
---|
5049 | nl.n_desc = 0;
|
---|
5050 | #ifdef N_SECT
|
---|
5051 | nl.n_sect = 0;
|
---|
5052 | #else
|
---|
5053 | nl.n_other = 0;
|
---|
5054 | #endif
|
---|
5055 | *bufp++ = nl;
|
---|
5056 | (*syms_written_addr)++;
|
---|
5057 | entry->local_syms_offset = *syms_written_addr * sizeof (struct nlist);
|
---|
5058 | }
|
---|
5059 |
|
---|
5060 | /* Read the file's string table. */
|
---|
5061 |
|
---|
5062 | entry->strings = (char *) ALLOCA (entry->strs_size);
|
---|
5063 | read_entry_strings (file_open (entry), entry);
|
---|
5064 |
|
---|
5065 | for (; p < end; p++)
|
---|
5066 | {
|
---|
5067 | register int type = p->n_type;
|
---|
5068 | register int write = 0;
|
---|
5069 |
|
---|
5070 | /* WRITE gets 1 for a non-global symbol that should be written. */
|
---|
5071 |
|
---|
5072 | if (SET_ELEMENT_P (type)) /* This occurs even if global. These */
|
---|
5073 | /* types of symbols are never written */
|
---|
5074 | /* globally, though they are stored */
|
---|
5075 | /* globally. */
|
---|
5076 | write = output_style == OUTPUT_RELOCATABLE;
|
---|
5077 | else if (WEAK_SYMBOL (type))
|
---|
5078 | ;
|
---|
5079 | else if (!(type & (N_STAB | N_EXT)))
|
---|
5080 | /* ordinary local symbol */
|
---|
5081 | write = ((discard_locals != DISCARD_ALL)
|
---|
5082 | && !(discard_locals == DISCARD_L &&
|
---|
5083 | (p->n_un.n_strx + entry->strings)[0] == LPREFIX)
|
---|
5084 | && type != N_WARNING);
|
---|
5085 | else if (!(type & N_EXT))
|
---|
5086 | /* debugger symbol */
|
---|
5087 | write = (strip_symbols == STRIP_NONE);
|
---|
5088 |
|
---|
5089 | if (write)
|
---|
5090 | {
|
---|
5091 | /* If this symbol has a name,
|
---|
5092 | allocate space for it in the output string table. */
|
---|
5093 |
|
---|
5094 | if (p->n_un.n_strx)
|
---|
5095 | p->n_un.n_strx = assign_string_table_index (p->n_un.n_strx
|
---|
5096 | + entry->strings);
|
---|
5097 |
|
---|
5098 | /* Output this symbol to the buffer and count it. */
|
---|
5099 |
|
---|
5100 | *bufp++ = *p;
|
---|
5101 | (*syms_written_addr)++;
|
---|
5102 | }
|
---|
5103 | }
|
---|
5104 |
|
---|
5105 | /* All the symbols are now in BUF; write them. */
|
---|
5106 |
|
---|
5107 | lseek (outdesc, output_syms_offset + output_syms_size, 0);
|
---|
5108 | mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);
|
---|
5109 | output_syms_size += sizeof (struct nlist) * (bufp - buf);
|
---|
5110 |
|
---|
5111 | /* Write the string-table data for the symbols just written,
|
---|
5112 | using the data in vectors `strtab_vector' and `strtab_lens'. */
|
---|
5113 |
|
---|
5114 | write_string_table ();
|
---|
5115 | FREEA (entry->strings);
|
---|
5116 | FREEA (strtab_vector);
|
---|
5117 | FREEA (strtab_lens);
|
---|
5118 | FREEA (buf);
|
---|
5119 | }
|
---|
5120 | |
---|
5121 |
|
---|
5122 | /* Copy any GDB symbol segments from the input files to the output file.
|
---|
5123 | The contents of the symbol segment is copied without change
|
---|
5124 | except that we store some information into the beginning of it. */
|
---|
5125 |
|
---|
5126 | void write_file_symseg (struct file_entry *entry);
|
---|
5127 |
|
---|
5128 | void
|
---|
5129 | write_symsegs ()
|
---|
5130 | {
|
---|
5131 | lseek (outdesc, output_symseg_offset, 0);
|
---|
5132 | each_file (write_file_symseg, 0);
|
---|
5133 | }
|
---|
5134 |
|
---|
5135 | void
|
---|
5136 | write_file_symseg (entry)
|
---|
5137 | struct file_entry *entry;
|
---|
5138 | {
|
---|
5139 | char buffer[4096];
|
---|
5140 | struct symbol_root root;
|
---|
5141 | int indesc, len, total;
|
---|
5142 |
|
---|
5143 | if (entry->symseg_size == 0)
|
---|
5144 | return;
|
---|
5145 |
|
---|
5146 | output_symseg_size += entry->symseg_size;
|
---|
5147 |
|
---|
5148 | /* This entry has a symbol segment. Read the root of the segment. */
|
---|
5149 |
|
---|
5150 | indesc = file_open (entry);
|
---|
5151 | lseek (indesc, entry->symseg_offset + entry->starting_offset, 0);
|
---|
5152 | if (sizeof root != read (indesc, &root, sizeof root))
|
---|
5153 | fatal_with_file ("premature end of file in symbol segment of ", entry);
|
---|
5154 |
|
---|
5155 | /* Store some relocation info into the root. */
|
---|
5156 |
|
---|
5157 | root.ldsymoff = entry->local_syms_offset;
|
---|
5158 | root.textrel = entry->text_start_address - entry->orig_text_address;
|
---|
5159 | root.datarel = entry->data_start_address - entry->orig_data_address;
|
---|
5160 | root.bssrel = entry->bss_start_address - entry->orig_bss_address;
|
---|
5161 | root.databeg = entry->data_start_address - root.datarel;
|
---|
5162 | root.bssbeg = entry->bss_start_address - root.bssrel;
|
---|
5163 |
|
---|
5164 | /* Write the modified root into the output file. */
|
---|
5165 |
|
---|
5166 | mywrite (&root, sizeof root, 1, outdesc);
|
---|
5167 |
|
---|
5168 | /* Copy the rest of the symbol segment unchanged. */
|
---|
5169 |
|
---|
5170 | total = entry->symseg_size - sizeof root;
|
---|
5171 |
|
---|
5172 | while (total > 0)
|
---|
5173 | {
|
---|
5174 | len = read (indesc, buffer, min (sizeof buffer, total));
|
---|
5175 |
|
---|
5176 | if (len != min (sizeof buffer, total))
|
---|
5177 | fatal_with_file ("premature end of file in symbol segment of ", entry);
|
---|
5178 | total -= len;
|
---|
5179 | mywrite (buffer, len, 1, outdesc);
|
---|
5180 | }
|
---|
5181 |
|
---|
5182 | file_close ();
|
---|
5183 | }
|
---|
5184 | |
---|
5185 |
|
---|
5186 | /* Define a special symbol (etext, edata, or end). NAME is the
|
---|
5187 | name of the symbol, with a leading underscore (whether or not this
|
---|
5188 | system uses such underscores). TYPE is its type (e.g. N_DATA | N_EXT).
|
---|
5189 | Store a symbol * for the symbol in *SYM if SYM is non-NULL. */
|
---|
5190 | static void
|
---|
5191 | symbol_define (name, type, sym)
|
---|
5192 | /* const */ char *name;
|
---|
5193 | int type;
|
---|
5194 | symbol **sym;
|
---|
5195 | {
|
---|
5196 | symbol *thesym;
|
---|
5197 |
|
---|
5198 | #if defined(nounderscore)
|
---|
5199 | /* Skip the leading underscore. */
|
---|
5200 | name++;
|
---|
5201 | #endif
|
---|
5202 |
|
---|
5203 | thesym = getsym (name);
|
---|
5204 | if (thesym->defined)
|
---|
5205 | {
|
---|
5206 | /* The symbol is defined in some input file. Don't mess with it. */
|
---|
5207 | if (sym)
|
---|
5208 | *sym = 0;
|
---|
5209 | }
|
---|
5210 | else
|
---|
5211 | {
|
---|
5212 | if (thesym->referenced)
|
---|
5213 | /* The symbol was not defined, and we are defining it now. */
|
---|
5214 | undefined_global_sym_count--;
|
---|
5215 | thesym->defined = type;
|
---|
5216 | thesym->referenced = 1;
|
---|
5217 | if (sym)
|
---|
5218 | *sym = thesym;
|
---|
5219 | }
|
---|
5220 | }
|
---|
5221 |
|
---|
5222 | /* Create the symbol table entries for `etext', `edata' and `end'. */
|
---|
5223 |
|
---|
5224 | void
|
---|
5225 | symtab_init ()
|
---|
5226 | {
|
---|
5227 | symbol_define ("_edata", N_DATA | N_EXT, &edata_symbol);
|
---|
5228 | symbol_define ("_etext", N_TEXT | N_EXT, &etext_symbol);
|
---|
5229 | symbol_define ("_end", N_BSS | N_EXT, &end_symbol);
|
---|
5230 |
|
---|
5231 | /* Either _edata or __edata (C names) is OK as far as ANSI is concerned
|
---|
5232 | (see section 4.1.2.1). In general, it is best to use __foo and
|
---|
5233 | not worry about the confusing rules for the _foo namespace.
|
---|
5234 | But HPUX 7.0 uses _edata, so we might as weel be consistent. */
|
---|
5235 | symbol_define ("__edata", N_DATA | N_EXT, &edata_symbol_alt);
|
---|
5236 | symbol_define ("__etext", N_TEXT | N_EXT, &etext_symbol_alt);
|
---|
5237 | symbol_define ("__end", N_BSS | N_EXT, &end_symbol_alt);
|
---|
5238 | }
|
---|
5239 |
|
---|
5240 | /* Compute the hash code for symbol name KEY. */
|
---|
5241 |
|
---|
5242 | int
|
---|
5243 | hash_string (key)
|
---|
5244 | char *key;
|
---|
5245 | {
|
---|
5246 | register char *cp;
|
---|
5247 | register int k;
|
---|
5248 |
|
---|
5249 | cp = key;
|
---|
5250 | k = 0;
|
---|
5251 | while (*cp)
|
---|
5252 | k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
|
---|
5253 |
|
---|
5254 | return k;
|
---|
5255 | }
|
---|
5256 | |
---|
5257 |
|
---|
5258 | /* Get the symbol table entry for the global symbol named KEY.
|
---|
5259 | Create one if there is none. */
|
---|
5260 |
|
---|
5261 | symbol *
|
---|
5262 | getsym (key)
|
---|
5263 | char *key;
|
---|
5264 | {
|
---|
5265 | register int hashval;
|
---|
5266 | register symbol *bp;
|
---|
5267 |
|
---|
5268 | /* Determine the proper bucket. */
|
---|
5269 |
|
---|
5270 | hashval = hash_string (key) % TABSIZE;
|
---|
5271 |
|
---|
5272 | /* Search the bucket. */
|
---|
5273 |
|
---|
5274 | for (bp = symtab[hashval]; bp; bp = bp->link)
|
---|
5275 | if (! strcmp (key, bp->name))
|
---|
5276 | return bp;
|
---|
5277 |
|
---|
5278 | /* Nothing was found; create a new symbol table entry. */
|
---|
5279 |
|
---|
5280 | bp = (symbol *) xmalloc (sizeof (symbol));
|
---|
5281 | bp->refs = 0;
|
---|
5282 | bp->name = (char *) xmalloc (strlen (key) + 1);
|
---|
5283 | strcpy (bp->name, key);
|
---|
5284 | bp->defined = 0;
|
---|
5285 | bp->referenced = 0;
|
---|
5286 | bp->trace = 0;
|
---|
5287 | bp->value = 0;
|
---|
5288 | bp->max_common_size = 0;
|
---|
5289 | bp->warning = 0;
|
---|
5290 | bp->undef_refs = 0;
|
---|
5291 | bp->multiply_defined = 0;
|
---|
5292 | bp->weak = 0;
|
---|
5293 |
|
---|
5294 | /* Add the entry to the bucket. */
|
---|
5295 |
|
---|
5296 | bp->link = symtab[hashval];
|
---|
5297 | symtab[hashval] = bp;
|
---|
5298 |
|
---|
5299 | ++num_hash_tab_syms;
|
---|
5300 |
|
---|
5301 | return bp;
|
---|
5302 | }
|
---|
5303 |
|
---|
5304 | /* Like `getsym' but return 0 if the symbol is not already known. */
|
---|
5305 |
|
---|
5306 | symbol *
|
---|
5307 | getsym_soft (key)
|
---|
5308 | char *key;
|
---|
5309 | {
|
---|
5310 | register int hashval;
|
---|
5311 | register symbol *bp;
|
---|
5312 |
|
---|
5313 | /* Determine which bucket. */
|
---|
5314 |
|
---|
5315 | hashval = hash_string (key) % TABSIZE;
|
---|
5316 |
|
---|
5317 | /* Search the bucket. */
|
---|
5318 |
|
---|
5319 | for (bp = symtab[hashval]; bp; bp = bp->link)
|
---|
5320 | if (! strcmp (key, bp->name))
|
---|
5321 | return bp;
|
---|
5322 |
|
---|
5323 | return 0;
|
---|
5324 | }
|
---|
5325 | |
---|
5326 |
|
---|
5327 | /* Report a usage error.
|
---|
5328 | Like fatal except prints a usage summary. */
|
---|
5329 |
|
---|
5330 | void
|
---|
5331 | usage (string, arg)
|
---|
5332 | char *string, *arg;
|
---|
5333 | {
|
---|
5334 | if (string)
|
---|
5335 | {
|
---|
5336 | fprintf (stderr, "%s: ", progname);
|
---|
5337 | fprintf (stderr, string, arg);
|
---|
5338 | fprintf (stderr, "\n");
|
---|
5339 | }
|
---|
5340 | fprintf (stderr, "\
|
---|
5341 | Usage: %s [-d] [-dc] [-dp] [-e symbol] [-l lib] [-n] [-noinhibit-exec]\n\
|
---|
5342 | [-nostdlib] [-o file] [-r] [-s] [-t] [-u symbol] [-x] [-y symbol]\n\
|
---|
5343 | [-z] [-A file] [-Bstatic] [-D size] [-L libdir] [-M] [-N]\n\
|
---|
5344 | [-S] [-T[{text,data}] addr] [-V prefix] [-X] [-Zdll-search]\n\
|
---|
5345 | [file...]\n", progname);
|
---|
5346 | exit (1);
|
---|
5347 | }
|
---|
5348 |
|
---|
5349 | /* Report a fatal error.
|
---|
5350 | STRING is a printf format string and ARG is one arg for it. */
|
---|
5351 |
|
---|
5352 | void fatal (char *string, ...)
|
---|
5353 | {
|
---|
5354 | va_list args;
|
---|
5355 | fprintf (stderr, "%s: ", progname);
|
---|
5356 | va_start (args, string);
|
---|
5357 | vfprintf (stderr, string, args);
|
---|
5358 | va_end (args);
|
---|
5359 | fprintf (stderr, "\n");
|
---|
5360 | exit (1);
|
---|
5361 | }
|
---|
5362 |
|
---|
5363 | /* Report a fatal error. The error message is STRING
|
---|
5364 | followed by the filename of ENTRY. */
|
---|
5365 |
|
---|
5366 | void
|
---|
5367 | fatal_with_file (string, entry)
|
---|
5368 | char *string;
|
---|
5369 | struct file_entry *entry;
|
---|
5370 | {
|
---|
5371 | fprintf (stderr, "%s: ", progname);
|
---|
5372 | fprintf (stderr, string);
|
---|
5373 | print_file_name (entry, stderr);
|
---|
5374 | fprintf (stderr, "\n");
|
---|
5375 | exit (1);
|
---|
5376 | }
|
---|
5377 |
|
---|
5378 | /* Report a fatal error using the message for the last failed system call,
|
---|
5379 | followed by the string NAME. */
|
---|
5380 |
|
---|
5381 | void
|
---|
5382 | perror_name (name)
|
---|
5383 | char *name;
|
---|
5384 | {
|
---|
5385 | char *s;
|
---|
5386 |
|
---|
5387 | if (errno < sys_nerr)
|
---|
5388 | s = concat ("", sys_errlist[errno], " for %s", NULL);
|
---|
5389 | else
|
---|
5390 | s = "cannot open %s";
|
---|
5391 | fatal (s, name);
|
---|
5392 | }
|
---|
5393 |
|
---|
5394 | /* Report a fatal error using the message for the last failed system call,
|
---|
5395 | followed by the name of file ENTRY. */
|
---|
5396 |
|
---|
5397 | void
|
---|
5398 | perror_file (entry)
|
---|
5399 | struct file_entry *entry;
|
---|
5400 | {
|
---|
5401 | char *s;
|
---|
5402 |
|
---|
5403 | if (errno < sys_nerr)
|
---|
5404 | s = concat ("", sys_errlist[errno], " for ", NULL);
|
---|
5405 | else
|
---|
5406 | s = "cannot open ";
|
---|
5407 | fatal_with_file (s, entry);
|
---|
5408 | }
|
---|
5409 |
|
---|
5410 | /* Report a nonfatal error.
|
---|
5411 | STRING is a format for printf, and ARG1 ... ARG3 are args for it. */
|
---|
5412 |
|
---|
5413 | void
|
---|
5414 | error (string, arg1, arg2, arg3)
|
---|
5415 | char *string, *arg1, *arg2, *arg3;
|
---|
5416 | {
|
---|
5417 | fprintf (stderr, "%s: ", progname);
|
---|
5418 | fprintf (stderr, string, arg1, arg2, arg3);
|
---|
5419 | fprintf (stderr, "\n");
|
---|
5420 | }
|
---|
5421 |
|
---|
5422 | |
---|
5423 |
|
---|
5424 | /* Output COUNT*ELTSIZE bytes of data at BUF
|
---|
5425 | to the descriptor DESC. */
|
---|
5426 |
|
---|
5427 | void
|
---|
5428 | mywrite (buf, count, eltsize, desc)
|
---|
5429 | void *buf;
|
---|
5430 | int count;
|
---|
5431 | int eltsize;
|
---|
5432 | int desc;
|
---|
5433 | {
|
---|
5434 | register int val;
|
---|
5435 | register int bytes = count * eltsize;
|
---|
5436 |
|
---|
5437 | while (bytes > 0)
|
---|
5438 | {
|
---|
5439 | val = write (desc, buf, bytes);
|
---|
5440 | if (val <= 0)
|
---|
5441 | perror_name (output_filename);
|
---|
5442 | buf = (char*)buf + val;
|
---|
5443 | bytes -= val;
|
---|
5444 | }
|
---|
5445 | }
|
---|
5446 |
|
---|
5447 | /* Output PADDING zero-bytes to descriptor OUTDESC.
|
---|
5448 | PADDING may be negative; in that case, do nothing. */
|
---|
5449 |
|
---|
5450 | void
|
---|
5451 | padfile (padding, outdesc)
|
---|
5452 | int padding;
|
---|
5453 | int outdesc;
|
---|
5454 | {
|
---|
5455 | register char *buf;
|
---|
5456 | if (padding <= 0)
|
---|
5457 | return;
|
---|
5458 |
|
---|
5459 | buf = (char *) ALLOCA (padding);
|
---|
5460 | bzero (buf, padding);
|
---|
5461 | mywrite (buf, padding, 1, outdesc);
|
---|
5462 | FREEA (buf);
|
---|
5463 | }
|
---|
5464 |
|
---|
5465 | /* Parse the string ARG using scanf format FORMAT, and return the result.
|
---|
5466 | If it does not parse, report fatal error
|
---|
5467 | generating the error message using format string ERROR and ARG as arg. */
|
---|
5468 |
|
---|
5469 | int
|
---|
5470 | parse (arg, format, error)
|
---|
5471 | char *arg, *format, *error;
|
---|
5472 | {
|
---|
5473 | int x;
|
---|
5474 | if (1 != sscanf (arg, format, &x))
|
---|
5475 | fatal (error, arg);
|
---|
5476 | return x;
|
---|
5477 | }
|
---|
5478 |
|
---|
5479 | /* Like malloc but get fatal error if memory is exhausted. */
|
---|
5480 |
|
---|
5481 | void *
|
---|
5482 | xmalloc (size)
|
---|
5483 | size_t size;
|
---|
5484 | {
|
---|
5485 | register char *result = malloc (size);
|
---|
5486 | if (!result)
|
---|
5487 | fatal ("virtual memory exhausted", 0);
|
---|
5488 | return result;
|
---|
5489 | }
|
---|
5490 |
|
---|
5491 | /* Like realloc but get fatal error if memory is exhausted. */
|
---|
5492 |
|
---|
5493 | void *
|
---|
5494 | xrealloc (ptr, size)
|
---|
5495 | void *ptr;
|
---|
5496 | size_t size;
|
---|
5497 | {
|
---|
5498 | register char *result = realloc (ptr, size);
|
---|
5499 | if (!result)
|
---|
5500 | fatal ("virtual memory exhausted", 0);
|
---|
5501 | return result;
|
---|
5502 | }
|
---|
5503 | |
---|
5504 |
|
---|
5505 | char *my_cplus_demangle (const char *mangled)
|
---|
5506 | {
|
---|
5507 | if (*mangled == '_')
|
---|
5508 | ++mangled;
|
---|
5509 | return cplus_demangle (mangled, demangle_options);
|
---|
5510 | }
|
---|
5511 |
|
---|
5512 | |
---|
5513 |
|
---|
5514 | /**
|
---|
5515 | * Generates an unique temporary file.
|
---|
5516 | *
|
---|
5517 | * @returns 0 on success.
|
---|
5518 | * @returns -1 on failure.
|
---|
5519 | * @param pszFile Where to put the filename.
|
---|
5520 | * @param pszPrefix Prefix.
|
---|
5521 | * @param pszSuffix Suffix.
|
---|
5522 | * @remark The code is nicked from the weak linker.
|
---|
5523 | * @remark sorry about the convention here, this is borrowed from elsewhere.
|
---|
5524 | */
|
---|
5525 | static int make_tempfile(char *pszFile, const char *pszPrefix, const char *pszSuffix)
|
---|
5526 | {
|
---|
5527 | struct stat s;
|
---|
5528 | unsigned c = 0;
|
---|
5529 | pid_t pid = getpid();
|
---|
5530 | const char * pszTmp = getenv("TMP");
|
---|
5531 | if (!pszTmp) pszTmp = getenv("TMPDIR");
|
---|
5532 | if (!pszTmp) pszTmp = getenv("TEMP");
|
---|
5533 | if (!pszTmp) pszTmp = ".";
|
---|
5534 |
|
---|
5535 | do
|
---|
5536 | {
|
---|
5537 | struct timeval tv = {0,0};
|
---|
5538 | if (c++ >= 200)
|
---|
5539 | return -1;
|
---|
5540 | gettimeofday(&tv, NULL);
|
---|
5541 | sprintf(pszFile, "%s\\%s%x%lx%d%lx%s", pszTmp, pszPrefix, pid, tv.tv_sec, c, tv.tv_usec, pszSuffix);
|
---|
5542 | } while (!stat(pszFile, &s));
|
---|
5543 |
|
---|
5544 | return 0;
|
---|
5545 | }
|
---|
5546 |
|
---|
5547 | /* list of converted libraries and objects which must be removed upon exit. */
|
---|
5548 | struct lx_tmp
|
---|
5549 | {
|
---|
5550 | struct lx_tmp *next;
|
---|
5551 | char *name;
|
---|
5552 | } *conv_list = NULL;
|
---|
5553 |
|
---|
5554 | /** Converts a .DLL to an temporary import library.
|
---|
5555 | * @remark sorry about the convention here, this is borrowed from elsewhere.
|
---|
5556 | */
|
---|
5557 | char *lx_to_aout (const char *pszFilename)
|
---|
5558 | {
|
---|
5559 | int rc;
|
---|
5560 | char * pszNewFile;
|
---|
5561 | struct lx_tmp *pName;
|
---|
5562 |
|
---|
5563 | /*
|
---|
5564 | * Make temporary file.
|
---|
5565 | */
|
---|
5566 | pName = (struct lx_tmp *)xmalloc(sizeof(*pName));
|
---|
5567 | pName->name = pszNewFile = xmalloc(_MAX_PATH);
|
---|
5568 | if (make_tempfile(pszNewFile, "ldconv", ".a"))
|
---|
5569 | {
|
---|
5570 | free(pszNewFile);
|
---|
5571 | return NULL;
|
---|
5572 | }
|
---|
5573 |
|
---|
5574 | /*
|
---|
5575 | * Do the conversion.
|
---|
5576 | */
|
---|
5577 | rc = spawnlp(P_WAIT, "emximp.exe", "emximp.exe",
|
---|
5578 | "-o", pszNewFile, pszFilename, NULL);
|
---|
5579 | if (!rc)
|
---|
5580 | {
|
---|
5581 | /* add to auto delete list for removal on exit(). */
|
---|
5582 | pName->next = conv_list;
|
---|
5583 | conv_list = pName;
|
---|
5584 | return pName->name;
|
---|
5585 |
|
---|
5586 | }
|
---|
5587 | free(pszNewFile);
|
---|
5588 | free(pName);
|
---|
5589 |
|
---|
5590 | fprintf (stderr, "emxomfld: a.out to omf conversion failed for '%s'.\n",
|
---|
5591 | pszFilename);
|
---|
5592 | exit (2);
|
---|
5593 | return NULL;
|
---|
5594 | }
|
---|
5595 |
|
---|
5596 |
|
---|
5597 | /**
|
---|
5598 | * Checks if the file FD is an LX DLL.
|
---|
5599 | *
|
---|
5600 | * @returns 1 if LX DLL.
|
---|
5601 | * @returns 0 if not LX DLL.
|
---|
5602 | * @param fd Handle to file to check.
|
---|
5603 | */
|
---|
5604 | int check_lx_dll(int fd)
|
---|
5605 | {
|
---|
5606 | unsigned long ul;
|
---|
5607 | char achMagic[2];
|
---|
5608 |
|
---|
5609 | if ( lseek(fd, 0, SEEK_SET)
|
---|
5610 | || read(fd, &achMagic, 2) != 2)
|
---|
5611 | goto thats_not_it;
|
---|
5612 |
|
---|
5613 | if (!memcmp(achMagic, "MZ", 2))
|
---|
5614 | {
|
---|
5615 | if ( lseek(fd, 0x3c, SEEK_SET)
|
---|
5616 | || read(fd, &ul, 4) != 4 /* offset of the 'new' header */
|
---|
5617 | || ul < 0x40
|
---|
5618 | || ul >= 0x10000000 /* 512MB stubs sure */
|
---|
5619 | || lseek(fd, ul, SEEK_SET)
|
---|
5620 | || read(fd, &achMagic, 2) != 2)
|
---|
5621 | goto thats_not_it;
|
---|
5622 | }
|
---|
5623 |
|
---|
5624 | if ( memcmp(achMagic, "LX", 2)
|
---|
5625 | || lseek(fd, 14, SEEK_CUR)
|
---|
5626 | || read(fd, &ul, 4) != 4) /*e32_mflags*/
|
---|
5627 | goto thats_not_it;
|
---|
5628 |
|
---|
5629 | #define E32MODDLL 0x08000L
|
---|
5630 | #define E32MODPROTDLL 0x18000L
|
---|
5631 | #define E32MODMASK 0x38000L
|
---|
5632 | if ( (ul & E32MODMASK) != E32MODDLL
|
---|
5633 | && (ul & E32MODMASK) != E32MODPROTDLL)
|
---|
5634 | goto thats_not_it;
|
---|
5635 |
|
---|
5636 | /* it's a LX DLL! */
|
---|
5637 | lseek(fd, 0, SEEK_SET);
|
---|
5638 | return 1;
|
---|
5639 |
|
---|
5640 |
|
---|
5641 | thats_not_it:
|
---|
5642 | lseek(fd, 0, SEEK_SET);
|
---|
5643 | return 0;
|
---|
5644 | }
|
---|
5645 |
|
---|
5646 | /* Generates a definition file for a dll which doesn't have one. */
|
---|
5647 |
|
---|
5648 | static void gen_deffile(void)
|
---|
5649 | {
|
---|
5650 | char * psz;
|
---|
5651 | struct lx_tmp *pName;
|
---|
5652 |
|
---|
5653 | /*
|
---|
5654 | * Make temporary file.
|
---|
5655 | */
|
---|
5656 | pName = (struct lx_tmp *)xmalloc(sizeof(*pName));
|
---|
5657 | pName->name = psz = (char *)xmalloc(_MAX_PATH);
|
---|
5658 | if (!make_tempfile(psz, "lddef", ".def"))
|
---|
5659 | {
|
---|
5660 | FILE *pFile = fopen(psz, "w");
|
---|
5661 | if (pFile)
|
---|
5662 | {
|
---|
5663 | const char *pszName = _getname(exe_filename);
|
---|
5664 | size_t cchName = strlen(pszName);
|
---|
5665 | if (cchName > 4 && !stricmp(pszName + cchName - 4, ".dll"))
|
---|
5666 | cchName -= 4;
|
---|
5667 | fprintf(pFile,
|
---|
5668 | ";; Autogenerated by ld\n"
|
---|
5669 | "LIBRARY %.*s INITINSTANCE TERMINSTANCE\n"
|
---|
5670 | "DATA MULTIPLE\n"
|
---|
5671 | "CODE SHARED\n"
|
---|
5672 | "\n",
|
---|
5673 | cchName, pszName);
|
---|
5674 | if (trace_files)
|
---|
5675 | fprintf(stderr,
|
---|
5676 | "--- Generated def-file %s:\n"
|
---|
5677 | ";; Autogenerated by ld\n"
|
---|
5678 | "LIBRARY %.*s INITINSTANCE TERMINSTANCE\n"
|
---|
5679 | "DATA MULTIPLE NONSHARED\n"
|
---|
5680 | "CODE SINGLE SHARED\n"
|
---|
5681 | "---- End of generated def-file.\n",
|
---|
5682 | psz, cchName, pszName);
|
---|
5683 | fclose(pFile);
|
---|
5684 | def_filename = psz;
|
---|
5685 |
|
---|
5686 | /* add to auto delete list for removal on exit(). */
|
---|
5687 | pName->next = conv_list;
|
---|
5688 | conv_list = pName;
|
---|
5689 | return;
|
---|
5690 | }
|
---|
5691 | }
|
---|
5692 | free(psz);
|
---|
5693 | free(pName);
|
---|
5694 | }
|
---|
5695 |
|
---|
5696 |
|
---|
5697 | /* atexit worker */
|
---|
5698 | void cleanup (void)
|
---|
5699 | {
|
---|
5700 | for (; conv_list; conv_list = conv_list->next)
|
---|
5701 | unlink (conv_list->name);
|
---|
5702 | }
|
---|