Linker.c 101 KB
Newer Older
1
/* -----------------------------------------------------------------------------
2
 * $Id: Linker.c,v 1.118 2003/03/31 14:02:32 simonmar Exp $
3
 *
4
 * (c) The GHC Team, 2000-2003
5
6
7
8
9
 *
 * RTS Object Linker
 *
 * ---------------------------------------------------------------------------*/

sof's avatar
sof committed
10
#if 0
11
#include "PosixSource.h"
sof's avatar
sof committed
12
#endif
13
14
15
16
17
#include "Rts.h"
#include "RtsFlags.h"
#include "HsFFI.h"
#include "Hash.h"
#include "Linker.h"
18
#include "LinkerInternals.h"
19
#include "RtsUtils.h"
20
#include "StoragePriv.h"
21
#include "Schedule.h"
22

23
#ifdef HAVE_SYS_TYPES_H
24
#include <sys/types.h>
25
26
#endif

27
28
29
#include <stdlib.h>
#include <string.h>

30
#ifdef HAVE_SYS_STAT_H
31
#include <sys/stat.h>
32
#endif
33

34
35
36
#if defined(HAVE_FRAMEWORK_HASKELLSUPPORT)
#include <HaskellSupport/dlfcn.h>
#elif defined(HAVE_DLFCN_H)
37
#include <dlfcn.h>
38
#endif
39

sof's avatar
sof committed
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#if defined(cygwin32_TARGET_OS)
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <regex.h>
#include <sys/fcntl.h>
#include <sys/termios.h>
#include <sys/utime.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#endif

56
57
58
59
60
61
#if defined(ia64_TARGET_ARCH)
#define USE_MMAP
#include <fcntl.h>
#include <sys/mman.h>
#endif

62
#if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) || defined(freebsd_TARGET_OS) || defined(netbsd_TARGET_OS)
63
#  define OBJFORMAT_ELF
64
#elif defined(cygwin32_TARGET_OS) || defined (mingw32_TARGET_OS)
65
#  define OBJFORMAT_PEi386
66
#  include <windows.h>
sof's avatar
sof committed
67
#  include <math.h>
68
#elif defined(darwin_TARGET_OS)
69
#  include <mach-o/ppc/reloc.h>
70
71
72
73
#  define OBJFORMAT_MACHO
#  include <mach-o/loader.h>
#  include <mach-o/nlist.h>
#  include <mach-o/reloc.h>
74
75
#endif

76
/* Hash table mapping symbol names to Symbol */
77
static /*Str*/HashTable *symhash;
78

79
80
81
/* List of currently loaded objects */
ObjectCode *objects = NULL;	/* initially empty */

82
#if defined(OBJFORMAT_ELF)
83
84
85
static int ocVerifyImage_ELF    ( ObjectCode* oc );
static int ocGetNames_ELF       ( ObjectCode* oc );
static int ocResolve_ELF        ( ObjectCode* oc );
86
#elif defined(OBJFORMAT_PEi386)
87
88
89
static int ocVerifyImage_PEi386 ( ObjectCode* oc );
static int ocGetNames_PEi386    ( ObjectCode* oc );
static int ocResolve_PEi386     ( ObjectCode* oc );
90
91
92
93
#elif defined(OBJFORMAT_MACHO)
static int ocVerifyImage_MachO    ( ObjectCode* oc );
static int ocGetNames_MachO       ( ObjectCode* oc );
static int ocResolve_MachO        ( ObjectCode* oc );
94
95

static void machoInitSymbolsWithoutUnderscore();
96
97
98
99
100
101
#endif

/* -----------------------------------------------------------------------------
 * Built-in symbols from the RTS
 */

102
103
104
105
106
107
typedef struct _RtsSymbolVal {
    char   *lbl;
    void   *addr;
} RtsSymbolVal;


108
109
110
111
112
113
114
115
116
117
118
#if !defined(PAR)
#define Maybe_ForeignObj        SymX(mkForeignObjzh_fast)

#define Maybe_Stable_Names      SymX(mkWeakzh_fast)			\
      				SymX(makeStableNamezh_fast)		\
      				SymX(finalizzeWeakzh_fast)
#else
/* These are not available in GUM!!! -- HWL */
#define Maybe_ForeignObj
#define Maybe_Stable_Names
#endif
119
120

#if !defined (mingw32_TARGET_OS)
121
#define RTS_POSIX_ONLY_SYMBOLS                  \
122
123
      SymX(stg_sig_install)			\
      Sym(nocldstop)
sof's avatar
sof committed
124
#endif
125

sof's avatar
sof committed
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#if defined (cygwin32_TARGET_OS)
#define RTS_MINGW_ONLY_SYMBOLS /**/
/* Don't have the ability to read import libs / archives, so
 * we have to stupidly list a lot of what libcygwin.a
 * exports; sigh. 
 */
#define RTS_CYGWIN_ONLY_SYMBOLS                 \
      SymX(regfree)                             \
      SymX(regexec)                             \
      SymX(regerror)                            \
      SymX(regcomp)                             \
      SymX(__errno)                             \
      SymX(access)                              \
      SymX(chmod)                               \
      SymX(chdir)                               \
      SymX(close)                               \
      SymX(creat)                               \
      SymX(dup)                                 \
      SymX(dup2)                                \
      SymX(fstat)                               \
      SymX(fcntl)                               \
      SymX(getcwd)                              \
      SymX(getenv)                              \
      SymX(lseek)                               \
      SymX(open)                                \
      SymX(fpathconf)                           \
      SymX(pathconf)                            \
      SymX(stat)                                \
      SymX(pow)                                 \
      SymX(tanh)                                \
      SymX(cosh)                                \
      SymX(sinh)                                \
      SymX(atan)                                \
      SymX(acos)                                \
      SymX(asin)                                \
      SymX(tan)                                 \
      SymX(cos)                                 \
      SymX(sin)                                 \
      SymX(exp)                                 \
      SymX(log)                                 \
      SymX(sqrt)                                \
      SymX(localtime_r)                         \
      SymX(gmtime_r)                            \
      SymX(mktime)                              \
      Sym(_imp___tzname)                        \
      SymX(gettimeofday)                        \
      SymX(timezone)                            \
      SymX(tcgetattr)                           \
      SymX(tcsetattr)                           \
      SymX(memcpy)                              \
      SymX(memmove)                             \
      SymX(realloc)                             \
      SymX(malloc)                              \
      SymX(free)                                \
      SymX(fork)                                \
      SymX(lstat)                               \
      SymX(isatty)                              \
      SymX(mkdir)                               \
      SymX(opendir)                             \
      SymX(readdir)                             \
      SymX(rewinddir)                           \
      SymX(closedir)                            \
      SymX(link)                                \
      SymX(mkfifo)                              \
      SymX(pipe)                                \
      SymX(read)                                \
      SymX(rename)                              \
      SymX(rmdir)                               \
      SymX(select)                              \
      SymX(system)                              \
      SymX(write)                               \
      SymX(strcmp)                              \
      SymX(strcpy)                              \
      SymX(strncpy)                             \
      SymX(strerror)                            \
      SymX(sigaddset)                           \
      SymX(sigemptyset)                         \
      SymX(sigprocmask)                         \
      SymX(umask)                               \
      SymX(uname)                               \
      SymX(unlink)                              \
      SymX(utime)                               \
208
      SymX(waitpid)
209

sof's avatar
sof committed
210
211
212
213
214
215
#elif !defined(mingw32_TARGET_OS)
#define RTS_MINGW_ONLY_SYMBOLS /**/
#define RTS_CYGWIN_ONLY_SYMBOLS /**/
#else /* defined(mingw32_TARGET_OS) */
#define RTS_POSIX_ONLY_SYMBOLS  /**/
#define RTS_CYGWIN_ONLY_SYMBOLS /**/
216
217
218

/* These are statically linked from the mingw libraries into the ghc
   executable, so we have to employ this hack. */
219
#define RTS_MINGW_ONLY_SYMBOLS                  \
sof's avatar
sof committed
220
221
      SymX(asyncReadzh_fast)			\
      SymX(asyncWritezh_fast)			\
222
      SymX(memset)                              \
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
      SymX(inet_ntoa)                           \
      SymX(inet_addr)                           \
      SymX(htonl)                               \
      SymX(recvfrom)                            \
      SymX(listen)                              \
      SymX(bind)                                \
      SymX(shutdown)                            \
      SymX(connect)                             \
      SymX(htons)                               \
      SymX(ntohs)                               \
      SymX(getservbyname)                       \
      SymX(getservbyport)                       \
      SymX(getprotobynumber)                    \
      SymX(getprotobyname)                      \
      SymX(gethostbyname)                       \
      SymX(gethostbyaddr)                       \
      SymX(gethostname)                         \
      SymX(strcpy)                              \
      SymX(strncpy)                             \
      SymX(abort)                               \
      Sym(_alloca)                              \
      Sym(isxdigit)                             \
      Sym(isupper)                              \
      Sym(ispunct)                              \
      Sym(islower)                              \
      Sym(isspace)                              \
      Sym(isprint)                              \
      Sym(isdigit)                              \
      Sym(iscntrl)                              \
      Sym(isalpha)                              \
      Sym(isalnum)                              \
      SymX(strcmp)                              \
255
256
257
      SymX(memmove)                             \
      SymX(realloc)                             \
      SymX(malloc)                              \
258
259
260
261
262
263
264
265
266
267
268
269
270
271
      SymX(pow)                                 \
      SymX(tanh)                                \
      SymX(cosh)                                \
      SymX(sinh)                                \
      SymX(atan)                                \
      SymX(acos)                                \
      SymX(asin)                                \
      SymX(tan)                                 \
      SymX(cos)                                 \
      SymX(sin)                                 \
      SymX(exp)                                 \
      SymX(log)                                 \
      SymX(sqrt)                                \
      SymX(memcpy)                              \
272
      Sym(mktime)                               \
273
      Sym(_imp___timezone)                      \
274
      Sym(_imp___tzname)                        \
275
      Sym(_imp___iob)                           \
276
277
278
279
      Sym(localtime)                            \
      Sym(gmtime)                               \
      Sym(opendir)                              \
      Sym(readdir)                              \
sof's avatar
sof committed
280
      Sym(rewinddir)                            \
281
      Sym(closedir)
282
#endif
283

sof's avatar
sof committed
284
285
286
287
288
#ifndef SMP
# define MAIN_CAP_SYM SymX(MainCapability)
#else
# define MAIN_CAP_SYM
#endif
289

290
#define RTS_SYMBOLS				\
291
292
293
      Maybe_ForeignObj				\
      Maybe_Stable_Names			\
      Sym(StgReturn)				\
294
295
296
      SymX(stg_enter_info)			\
      SymX(stg_enter_ret)			\
      SymX(stg_gc_void_info)			\
297
298
      SymX(__stg_gc_enter_1)			\
      SymX(stg_gc_noregs)			\
299
      SymX(stg_gc_unpt_r1_info)			\
300
      SymX(stg_gc_unpt_r1)			\
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
      SymX(stg_gc_unbx_r1_info)			\
      SymX(stg_gc_unbx_r1)			\
      SymX(stg_gc_f1_info)			\
      SymX(stg_gc_f1)				\
      SymX(stg_gc_d1_info)			\
      SymX(stg_gc_d1)				\
      SymX(stg_gc_l1_info)			\
      SymX(stg_gc_l1)				\
      SymX(__stg_gc_fun)			\
      SymX(stg_gc_fun_info)			\
      SymX(stg_gc_fun_ret)			\
      SymX(stg_gc_gen)				\
      SymX(stg_gc_gen_info)			\
      SymX(stg_gc_gen_hp)			\
      SymX(stg_gc_ut)				\
      SymX(stg_gen_yield)			\
      SymX(stg_yield_noregs)			\
318
      SymX(stg_yield_to_interpreter)		\
319
320
321
322
323
324
      SymX(stg_gen_block)			\
      SymX(stg_block_noregs)			\
      SymX(stg_block_1)				\
      SymX(stg_block_takemvar)			\
      SymX(stg_block_putmvar)			\
      SymX(stg_seq_frame_info)			\
325
      SymX(ErrorHdrHook)			\
sof's avatar
sof committed
326
      MAIN_CAP_SYM                              \
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
      SymX(MallocFailHook)			\
      SymX(OnExitHook)				\
      SymX(OutOfHeapHook)			\
      SymX(PatErrorHdrHook)			\
      SymX(PostTraceHook)			\
      SymX(PreTraceHook)			\
      SymX(StackOverflowHook)			\
      SymX(__encodeDouble)			\
      SymX(__encodeFloat)			\
      SymX(__gmpn_gcd_1)			\
      SymX(__gmpz_cmp)				\
      SymX(__gmpz_cmp_si)			\
      SymX(__gmpz_cmp_ui)			\
      SymX(__gmpz_get_si)			\
      SymX(__gmpz_get_ui)			\
      SymX(__int_encodeDouble)			\
      SymX(__int_encodeFloat)			\
      SymX(andIntegerzh_fast)			\
      SymX(blockAsyncExceptionszh_fast)		\
      SymX(catchzh_fast)			\
      SymX(cmp_thread)				\
      SymX(complementIntegerzh_fast)		\
sof's avatar
sof committed
349
350
      SymX(cmpIntegerzh_fast)	        	\
      SymX(cmpIntegerIntzh_fast)	      	\
351
352
353
354
355
      SymX(createAdjustor)			\
      SymX(decodeDoublezh_fast)			\
      SymX(decodeFloatzh_fast)			\
      SymX(defaultsHook)			\
      SymX(delayzh_fast)			\
sof's avatar
sof committed
356
357
      SymX(deRefWeakzh_fast)			\
      SymX(deRefStablePtrzh_fast)		\
358
359
360
      SymX(divExactIntegerzh_fast)		\
      SymX(divModIntegerzh_fast)		\
      SymX(forkzh_fast)				\
361
      SymX(forkProcesszh_fast)                  \
362
      SymX(freeHaskellFunctionPtr)		\
sof's avatar
sof committed
363
      SymX(freeStablePtr)		        \
364
      SymX(gcdIntegerzh_fast)			\
sof's avatar
sof committed
365
366
      SymX(gcdIntegerIntzh_fast)		\
      SymX(gcdIntzh_fast)			\
367
368
369
      SymX(getProgArgv)				\
      SymX(getStablePtr)			\
      SymX(int2Integerzh_fast)			\
sof's avatar
sof committed
370
371
      SymX(integer2Intzh_fast)			\
      SymX(integer2Wordzh_fast)			\
372
373
374
375
      SymX(isDoubleDenormalized)		\
      SymX(isDoubleInfinite)			\
      SymX(isDoubleNaN)				\
      SymX(isDoubleNegativeZero)		\
sof's avatar
sof committed
376
      SymX(isEmptyMVarzh_fast)			\
377
378
379
380
381
      SymX(isFloatDenormalized)			\
      SymX(isFloatInfinite)			\
      SymX(isFloatNaN)				\
      SymX(isFloatNegativeZero)			\
      SymX(killThreadzh_fast)			\
sof's avatar
sof committed
382
      SymX(makeStablePtrzh_fast)		\
383
384
      SymX(minusIntegerzh_fast)			\
      SymX(mkApUpd0zh_fast)			\
sof's avatar
sof committed
385
      SymX(myThreadIdzh_fast)			\
386
      SymX(labelThreadzh_fast)                  \
387
388
389
      SymX(newArrayzh_fast)			\
      SymX(newBCOzh_fast)			\
      SymX(newByteArrayzh_fast)			\
390
      SymX_redirect(newCAF, newDynCAF)		\
391
392
      SymX(newMVarzh_fast)			\
      SymX(newMutVarzh_fast)			\
393
      SymX(atomicModifyMutVarzh_fast)		\
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
      SymX(newPinnedByteArrayzh_fast)		\
      SymX(orIntegerzh_fast)			\
      SymX(performGC)				\
      SymX(plusIntegerzh_fast)			\
      SymX(prog_argc)				\
      SymX(prog_argv)				\
      SymX(putMVarzh_fast)			\
      SymX(quotIntegerzh_fast)			\
      SymX(quotRemIntegerzh_fast)		\
      SymX(raisezh_fast)			\
      SymX(remIntegerzh_fast)			\
      SymX(resetNonBlockingFd)			\
      SymX(resumeThread)			\
      SymX(rts_apply)				\
      SymX(rts_checkSchedStatus)		\
      SymX(rts_eval)				\
      SymX(rts_evalIO)				\
      SymX(rts_evalLazyIO)			\
      SymX(rts_eval_)				\
      SymX(rts_getBool)				\
      SymX(rts_getChar)				\
      SymX(rts_getDouble)			\
      SymX(rts_getFloat)			\
      SymX(rts_getInt)				\
      SymX(rts_getInt32)			\
      SymX(rts_getPtr)				\
420
      SymX(rts_getFunPtr)			\
421
      SymX(rts_getStablePtr)			\
422
      SymX(rts_getThreadId)			\
423
424
      SymX(rts_getWord)				\
      SymX(rts_getWord32)			\
425
      SymX(rts_lock)				\
426
427
428
429
430
431
432
433
434
435
      SymX(rts_mkBool)				\
      SymX(rts_mkChar)				\
      SymX(rts_mkDouble)			\
      SymX(rts_mkFloat)				\
      SymX(rts_mkInt)				\
      SymX(rts_mkInt16)				\
      SymX(rts_mkInt32)				\
      SymX(rts_mkInt64)				\
      SymX(rts_mkInt8)				\
      SymX(rts_mkPtr)				\
436
      SymX(rts_mkFunPtr)			\
437
438
439
440
441
442
443
      SymX(rts_mkStablePtr)			\
      SymX(rts_mkString)			\
      SymX(rts_mkWord)				\
      SymX(rts_mkWord16)			\
      SymX(rts_mkWord32)			\
      SymX(rts_mkWord64)			\
      SymX(rts_mkWord8)				\
444
      SymX(rts_unlock)				\
445
      SymX(run_queue_hd)			\
446
      SymX(setProgArgv)				\
447
448
      SymX(startupHaskell)			\
      SymX(shutdownHaskell)			\
449
450
451
452
453
454
455
456
457
458
      SymX(shutdownHaskellAndExit)		\
      SymX(stable_ptr_table)			\
      SymX(stackOverflow)			\
      SymX(stg_CAF_BLACKHOLE_info)		\
      SymX(stg_CHARLIKE_closure)		\
      SymX(stg_EMPTY_MVAR_info)			\
      SymX(stg_IND_STATIC_info)			\
      SymX(stg_INTLIKE_closure)			\
      SymX(stg_MUT_ARR_PTRS_FROZEN_info)	\
      SymX(stg_WEAK_info)                       \
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
      SymX(stg_ap_v_info)			\
      SymX(stg_ap_f_info)			\
      SymX(stg_ap_d_info)			\
      SymX(stg_ap_l_info)			\
      SymX(stg_ap_n_info)			\
      SymX(stg_ap_p_info)			\
      SymX(stg_ap_pv_info)			\
      SymX(stg_ap_pp_info)			\
      SymX(stg_ap_ppv_info)			\
      SymX(stg_ap_ppp_info)			\
      SymX(stg_ap_pppp_info)			\
      SymX(stg_ap_ppppp_info)			\
      SymX(stg_ap_pppppp_info)			\
      SymX(stg_ap_ppppppp_info)			\
      SymX(stg_ap_0_ret)			\
      SymX(stg_ap_v_ret)			\
      SymX(stg_ap_f_ret)			\
      SymX(stg_ap_d_ret)			\
      SymX(stg_ap_l_ret)			\
      SymX(stg_ap_n_ret)			\
      SymX(stg_ap_p_ret)			\
      SymX(stg_ap_pv_ret)			\
      SymX(stg_ap_pp_ret)			\
      SymX(stg_ap_ppv_ret)			\
      SymX(stg_ap_ppp_ret)			\
      SymX(stg_ap_pppp_ret)			\
      SymX(stg_ap_ppppp_ret)			\
      SymX(stg_ap_pppppp_ret)			\
      SymX(stg_ap_ppppppp_ret)			\
488
      SymX(stg_ap_1_upd_info)			\
489
490
491
492
493
494
495
      SymX(stg_ap_2_upd_info)			\
      SymX(stg_ap_3_upd_info)			\
      SymX(stg_ap_4_upd_info)			\
      SymX(stg_ap_5_upd_info)			\
      SymX(stg_ap_6_upd_info)			\
      SymX(stg_ap_7_upd_info)			\
      SymX(stg_ap_8_upd_info)			\
496
      SymX(stg_exit)				\
497
      SymX(stg_sel_0_upd_info)			\
498
499
500
501
502
503
      SymX(stg_sel_10_upd_info)			\
      SymX(stg_sel_11_upd_info)			\
      SymX(stg_sel_12_upd_info)			\
      SymX(stg_sel_13_upd_info)			\
      SymX(stg_sel_14_upd_info)			\
      SymX(stg_sel_15_upd_info)			\
504
505
506
507
508
509
510
511
512
      SymX(stg_sel_1_upd_info)			\
      SymX(stg_sel_2_upd_info)			\
      SymX(stg_sel_3_upd_info)			\
      SymX(stg_sel_4_upd_info)			\
      SymX(stg_sel_5_upd_info)			\
      SymX(stg_sel_6_upd_info)			\
      SymX(stg_sel_7_upd_info)			\
      SymX(stg_sel_8_upd_info)			\
      SymX(stg_sel_9_upd_info)			\
513
514
      SymX(stg_upd_frame_info)			\
      SymX(suspendThread)			\
515
      SymX(takeMVarzh_fast)			\
516
      SymX(timesIntegerzh_fast)			\
517
      SymX(tryPutMVarzh_fast)			\
518
519
520
      SymX(tryTakeMVarzh_fast)			\
      SymX(unblockAsyncExceptionszh_fast)	\
      SymX(unsafeThawArrayzh_fast)		\
521
522
      SymX(waitReadzh_fast)			\
      SymX(waitWritezh_fast)			\
523
524
      SymX(word2Integerzh_fast)			\
      SymX(xorIntegerzh_fast)			\
525
      SymX(yieldzh_fast)
526

527
#ifdef SUPPORT_LONG_LONGS
528
#define RTS_LONG_LONG_SYMS			\
529
530
      SymX(int64ToIntegerzh_fast)		\
      SymX(word64ToIntegerzh_fast)
531
532
533
534
#else
#define RTS_LONG_LONG_SYMS /* nothing */
#endif

535
536
537
// 64-bit support functions in libgcc.a
#if defined(__GNUC__) && SIZEOF_VOID_P <= 4
#define RTS_LIBGCC_SYMBOLS			\
538
539
540
      Sym(__divdi3)                             \
      Sym(__udivdi3)                            \
      Sym(__moddi3)                             \
541
542
543
544
545
      Sym(__umoddi3)				\
      Sym(__ashldi3)				\
      Sym(__ashrdi3)				\
      Sym(__lshrdi3)				\
      Sym(__eprintf)
546
547
548
549
550
551
552
553
554
#else
#define RTS_LIBGCC_SYMBOLS
#endif

#ifdef ia64_TARGET_ARCH
/* force these symbols to be present */
#define RTS_EXTRA_SYMBOLS			\
      Sym(__divsf3)
#elif defined(powerpc_TARGET_ARCH)
555
556
557
558
559
560
      // Symbols that don't have a leading underscore
      // on Mac OS X. They have to receive special treatment,
      // see machoInitSymbolsWithoutUnderscore()
#define RTS_MACHO_NOUNDERLINE_SYMBOLS		\
      Sym(saveFP)				\
      Sym(restFP)
561
562
563
#else
#define RTS_EXTRA_SYMBOLS /* nothing */
#endif
564
565
566
567

/* entirely bogus claims about types of these symbols */
#define Sym(vvv)  extern void (vvv);
#define SymX(vvv) /**/
568
#define SymX_redirect(vvv,xxx) /**/
569
RTS_SYMBOLS
570
RTS_LONG_LONG_SYMS
571
RTS_EXTRA_SYMBOLS
572
RTS_POSIX_ONLY_SYMBOLS
573
RTS_MINGW_ONLY_SYMBOLS
sof's avatar
sof committed
574
RTS_CYGWIN_ONLY_SYMBOLS
575
RTS_LIBGCC_SYMBOLS
576
577
#undef Sym
#undef SymX
578
#undef SymX_redirect
579
580
581
582
583
584
585
586
587
588
589

#ifdef LEADING_UNDERSCORE
#define MAYBE_LEADING_UNDERSCORE_STR(s) ("_" s)
#else
#define MAYBE_LEADING_UNDERSCORE_STR(s) (s)
#endif

#define Sym(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
                    (void*)(&(vvv)) },
#define SymX(vvv) Sym(vvv)

590
591
592
593
594
595
// SymX_redirect allows us to redirect references to one symbol to
// another symbol.  See newCAF/newDynCAF for an example.
#define SymX_redirect(vvv,xxx) \
    { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
      (void*)(&(xxx)) },

596
static RtsSymbolVal rtsSyms[] = {
597
      RTS_SYMBOLS
598
      RTS_LONG_LONG_SYMS
599
      RTS_EXTRA_SYMBOLS
600
      RTS_POSIX_ONLY_SYMBOLS
601
      RTS_MINGW_ONLY_SYMBOLS
sof's avatar
sof committed
602
      RTS_CYGWIN_ONLY_SYMBOLS
603
      RTS_LIBGCC_SYMBOLS
604
605
606
      { 0, 0 } /* sentinel */
};

607
608
609
610
611
/* -----------------------------------------------------------------------------
 * Insert symbols into hash tables, checking for duplicates.
 */
static void ghciInsertStrHashTable ( char* obj_name,
                                     HashTable *table,
612
                                     char* key,
613
614
615
616
617
618
619
620
                                     void *data
				   )
{
   if (lookupHashTable(table, (StgWord)key) == NULL)
   {
      insertStrHashTable(table, (StgWord)key, data);
      return;
   }
621
   fprintf(stderr,
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
      "\n\n"
      "GHCi runtime linker: fatal error: I found a duplicate definition for symbol\n"
      "   %s\n"
      "whilst processing object file\n"
      "   %s\n"
      "This could be caused by:\n"
      "   * Loading two different object files which export the same symbol\n"
      "   * Specifying the same object file twice on the GHCi command line\n"
      "   * An incorrect `package.conf' entry, causing some object to be\n"
      "     loaded twice.\n"
      "GHCi cannot safely continue in this situation.  Exiting now.  Sorry.\n"
      "\n",
      (char*)key,
      obj_name
   );
   exit(1);
}


641
642
643
/* -----------------------------------------------------------------------------
 * initialize the object linker
 */
644
645
646
647


static int linker_init_done = 0 ;

648
#if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
649
static void *dl_prog_handle;
650
#endif
651
652
653
654

void
initLinker( void )
{
655
    RtsSymbolVal *sym;
656

657
658
659
660
661
662
663
    /* Make initLinker idempotent, so we can call it
       before evey relevant operation; that means we
       don't need to initialise the linker separately */
    if (linker_init_done == 1) { return; } else {
      linker_init_done = 1;
    }

664
665
666
667
    symhash = allocStrHashTable();

    /* populate the symbol table with stuff from the RTS */
    for (sym = rtsSyms; sym->lbl != NULL; sym++) {
668
669
	ghciInsertStrHashTable("(GHCi built-in symbols)",
                               symhash, sym->lbl, sym->addr);
670
    }
671
672
673
674
#   if defined(OBJFORMAT_MACHO)
    machoInitSymbolsWithoutUnderscore();
#   endif

675
#   if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
676
    dl_prog_handle = dlopen(NULL, RTLD_LAZY);
677
#   endif
678
679
}

680
/* -----------------------------------------------------------------------------
681
682
683
 *                  Loading DLL or .so dynamic libraries
 * -----------------------------------------------------------------------------
 *
684
685
686
687
 * Add a DLL from which symbols may be found.  In the ELF case, just
 * do RTLD_GLOBAL-style add, so no further messing around needs to
 * happen in order that symbols in the loaded .so are findable --
 * lookupSymbol() will subsequently see them by dlsym on the program's
688
689
 * dl-handle.  Returns NULL if success, otherwise ptr to an err msg.
 *
690
 * In the PEi386 case, open the DLLs and put handles to them in a
691
 * linked list.  When looking for a symbol, try all handles in the
692
693
694
695
696
697
 * list.  This means that we need to load even DLLs that are guaranteed
 * to be in the ghc.exe image already, just so we can get a handle
 * to give to loadSymbol, so that we can find the symbols.  For such
 * libraries, the LoadLibrary call should be a no-op except for returning
 * the handle.
 * 
698
 */
699
700
701
702
703
704

#if defined(OBJFORMAT_PEi386)
/* A record for storing handles into DLLs. */

typedef
   struct _OpenedDLL {
705
      char*              name;
706
707
      struct _OpenedDLL* next;
      HINSTANCE instance;
708
   }
709
710
711
712
713
714
   OpenedDLL;

/* A list thereof. */
static OpenedDLL* opened_dlls = NULL;
#endif

715
716
char *
addDLL( char *dll_name )
717
{
718
#  if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
719
   /* ------------------- ELF DLL loader ------------------- */
720
   void *hdl;
721
   char *errmsg;
722

723
724
   initLinker();

725
   hdl= dlopen(dll_name, RTLD_NOW | RTLD_GLOBAL);
726
727
728
729
730
731
732
733
   if (hdl == NULL) {
      /* dlopen failed; return a ptr to the error msg. */
      errmsg = dlerror();
      if (errmsg == NULL) errmsg = "addDLL: unknown error";
      return errmsg;
   } else {
      return NULL;
   }
734
735
   /*NOTREACHED*/

736
#  elif defined(OBJFORMAT_PEi386)
737
   /* ------------------- Win32 DLL loader ------------------- */
738

739
   char*      buf;
740
   OpenedDLL* o_dll;
741
   HINSTANCE  instance;
742

743
744
745
   initLinker();

   /* fprintf(stderr, "\naddDLL; dll_name = `%s'\n", dll_name); */
746
747
748
749
750

   /* See if we've already got it, and ignore if so. */
   for (o_dll = opened_dlls; o_dll != NULL; o_dll = o_dll->next) {
      if (0 == strcmp(o_dll->name, dll_name))
         return NULL;
751
752
   }

753
754
755
756
757
758
759
760
761
762
   /* The file name has no suffix (yet) so that we can try
      both foo.dll and foo.drv

      The documentation for LoadLibrary says:
      	If no file name extension is specified in the lpFileName
      	parameter, the default library extension .dll is
      	appended. However, the file name string can include a trailing
      	point character (.) to indicate that the module name has no
      	extension. */

763
   buf = stgMallocBytes(strlen(dll_name) + 10, "addDLL");
764
765
766
   sprintf(buf, "%s.DLL", dll_name);
   instance = LoadLibrary(buf);
   if (instance == NULL) {
767
	 sprintf(buf, "%s.DRV", dll_name);	// KAA: allow loading of drivers (like winspool.drv)
768
769
	 instance = LoadLibrary(buf);
	 if (instance == NULL) {
sof's avatar
sof committed
770
		stgFree(buf);
771
772
773
774

	    /* LoadLibrary failed; return a ptr to the error msg. */
	    return "addDLL: unknown error";
   	 }
775
   }
sof's avatar
sof committed
776
   stgFree(buf);
777

778
   /* Add this DLL to the list of DLLs in which to search for symbols. */
779
   o_dll = stgMallocBytes( sizeof(OpenedDLL), "addDLL" );
780
781
   o_dll->name     = stgMallocBytes(1+strlen(dll_name), "addDLL");
   strcpy(o_dll->name, dll_name);
782
   o_dll->instance = instance;
783
784
   o_dll->next     = opened_dlls;
   opened_dlls     = o_dll;
785
786

   return NULL;
787
788
789
790
791
#  else
   barf("addDLL: not implemented on this platform");
#  endif
}

792
793
/* -----------------------------------------------------------------------------
 * lookup a symbol in the hash table
794
 */
795
796
797
void *
lookupSymbol( char *lbl )
{
798
    void *val;
799
    initLinker() ;
800
    ASSERT(symhash != NULL);
801
802
803
    val = lookupStrHashTable(symhash, lbl);

    if (val == NULL) {
804
#       if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
805
	return dlsym(dl_prog_handle, lbl);
806
#       elif defined(OBJFORMAT_PEi386)
807
808
809
        OpenedDLL* o_dll;
        void* sym;
        for (o_dll = opened_dlls; o_dll != NULL; o_dll = o_dll->next) {
sof's avatar
sof committed
810
	  /* fprintf(stderr, "look in %s for %s\n", o_dll->name, lbl); */
811
812
813
814
815
816
817
           if (lbl[0] == '_') {
              /* HACK: if the name has an initial underscore, try stripping
                 it off & look that up first. I've yet to verify whether there's
                 a Rule that governs whether an initial '_' *should always* be
                 stripped off when mapping from import lib name to the DLL name.
              */
              sym = GetProcAddress(o_dll->instance, (lbl+1));
sof's avatar
sof committed
818
819
820
              if (sym != NULL) {
		/*fprintf(stderr, "found %s in %s\n", lbl+1,o_dll->name); fflush(stderr);*/
		return sym;
821
	      }
822
           }
823
           sym = GetProcAddress(o_dll->instance, lbl);
sof's avatar
sof committed
824
825
826
827
           if (sym != NULL) {
	     /*fprintf(stderr, "found %s in %s\n", lbl,o_dll->name); fflush(stderr);*/
	     return sym;
	   }
828
        }
829
        return NULL;
ken's avatar
ken committed
830
831
832
#       else
        ASSERT(2+2 == 5);
        return NULL;
833
#       endif
834
    } else {
835
	return val;
836
837
838
    }
}

839
static
840
__attribute((unused))
841
842
843
void *
lookupLocalSymbol( ObjectCode* oc, char *lbl )
{
844
    void *val;
845
    initLinker() ;
846
847
848
849
850
    val = lookupStrHashTable(oc->lochash, lbl);

    if (val == NULL) {
        return NULL;
    } else {
851
	return val;
852
853
854
855
    }
}


856
857
858
859
860
861
862
863
864
865
866
867
868
869
/* -----------------------------------------------------------------------------
 * Debugging aid: look in GHCi's object symbol tables for symbols
 * within DELTA bytes of the specified address, and show their names.
 */
#ifdef DEBUG
void ghci_enquire ( char* addr );

void ghci_enquire ( char* addr )
{
   int   i;
   char* sym;
   char* a;
   const int DELTA = 64;
   ObjectCode* oc;
870
871
872

   initLinker();

873
874
875
876
   for (oc = objects; oc; oc = oc->next) {
      for (i = 0; i < oc->n_symbols; i++) {
         sym = oc->symbols[i];
         if (sym == NULL) continue;
877
         // fprintf(stderr, "enquire %p %p\n", sym, oc->lochash);
878
         a = NULL;
879
         if (oc->lochash != NULL) {
880
            a = lookupStrHashTable(oc->lochash, sym);
881
882
	 }
         if (a == NULL) {
883
            a = lookupStrHashTable(symhash, sym);
884
	 }
885
         if (a == NULL) {
886
	     // fprintf(stderr, "ghci_enquire: can't find %s\n", sym);
887
         }
888
889
890
891
892
893
894
895
         else if (addr-DELTA <= a && a <= addr+DELTA) {
            fprintf(stderr, "%p + %3d  ==  `%s'\n", addr, a - addr, sym);
         }
      }
   }
}
#endif

896
897
898
#ifdef ia64_TARGET_ARCH
static unsigned int PLTSize(void);
#endif
899

900
901
902
903
904
905
906
907
908
909
910
/* -----------------------------------------------------------------------------
 * Load an obj (populate the global symbol table, but don't resolve yet)
 *
 * Returns: 1 if ok, 0 on error.
 */
HsInt
loadObj( char *path )
{
   ObjectCode* oc;
   struct stat st;
   int r, n;
911
912
913
914
#ifdef USE_MMAP
   int fd, pagesize;
   void *map_addr;
#else
915
   FILE *f;
916
#endif
917

918
919
   initLinker();

920
   /* fprintf(stderr, "loadObj %s\n", path ); */
921
922
923

   /* Check that we haven't already loaded this object.  Don't give up
      at this stage; ocGetNames_* will barf later. */
924
   {
925
       ObjectCode *o;
926
927
928
929
930
931
       int is_dup = 0;
       for (o = objects; o; o = o->next) {
          if (0 == strcmp(o->fileName, path))
             is_dup = 1;
       }
       if (is_dup) {
932
	 fprintf(stderr,
933
934
935
936
937
938
939
940
            "\n\n"
            "GHCi runtime linker: warning: looks like you're trying to load the\n"
            "same object file twice:\n"
            "   %s\n"
            "GHCi will continue, but a duplicate-symbol error may shortly follow.\n"
            "\n"
            , path);
       }
941
942
943
944
   }

   oc = stgMallocBytes(sizeof(ObjectCode), "loadObj(oc)");

945
#  if defined(OBJFORMAT_ELF)
946
   oc->formatName = "ELF";
947
#  elif defined(OBJFORMAT_PEi386)
948
   oc->formatName = "PEi386";
949
950
#  elif defined(OBJFORMAT_MACHO)
   oc->formatName = "Mach-O";
951
#  else
sof's avatar
sof committed
952
   stgFree(oc);
953
954
955
956
957
958
   barf("loadObj: not implemented on this platform");
#  endif

   r = stat(path, &st);
   if (r == -1) { return 0; }

959
   /* sigh, strdup() isn't a POSIX function, so do it the long way */
960
961
962
   oc->fileName = stgMallocBytes( strlen(path)+1, "loadObj" );
   strcpy(oc->fileName, path);

963
964
965
   oc->fileSize          = st.st_size;
   oc->symbols           = NULL;
   oc->sections          = NULL;
966
   oc->lochash           = allocStrHashTable();
967
   oc->proddables        = NULL;
968
969
970
971
972

   /* chain it onto the list of objects */
   oc->next              = objects;
   objects               = oc;

973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
#ifdef USE_MMAP
#define ROUND_UP(x,size) ((x + size - 1) & ~(size - 1))

   /* On many architectures malloc'd memory isn't executable, so we need to use mmap. */

   fd = open(path, O_RDONLY);
   if (fd == -1)
      barf("loadObj: can't open `%s'", path);

   pagesize = getpagesize();

#ifdef ia64_TARGET_ARCH
   /* The PLT needs to be right before the object */
   n = ROUND_UP(PLTSize(), pagesize);
   oc->plt = mmap(NULL, n, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
   if (oc->plt == MAP_FAILED)
      barf("loadObj: can't allocate PLT");

   oc->pltIndex = 0;
   map_addr = oc->plt + n;
#endif

   n = ROUND_UP(oc->fileSize, pagesize);
   oc->image = mmap(map_addr, n, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
   if (oc->image == MAP_FAILED)
      barf("loadObj: can't map `%s'", path);

   close(fd);

#else /* !USE_MMAP */

   oc->image = stgMallocBytes(oc->fileSize, "loadObj(image)");

1006
1007
   /* load the image into memory */
   f = fopen(path, "rb");
1008
   if (!f)
1009
       barf("loadObj: can't read `%s'", path);
1010

1011
   n = fread ( oc->image, 1, oc->fileSize, f );
1012
   if (n != oc->fileSize)
1013
      barf("loadObj: error whilst reading `%s'", path);
1014
1015
1016
1017

   fclose(f);

#endif /* USE_MMAP */
1018
1019

   /* verify the in-memory image */
1020
#  if defined(OBJFORMAT_ELF)
1021
   r = ocVerifyImage_ELF ( oc );
1022
#  elif defined(OBJFORMAT_PEi386)
1023
   r = ocVerifyImage_PEi386 ( oc );
1024
1025
#  elif defined(OBJFORMAT_MACHO)
   r = ocVerifyImage_MachO ( oc );
1026
1027
1028
1029
1030
1031
#  else
   barf("loadObj: no verify method");
#  endif
   if (!r) { return r; }

   /* build the symbol list for this image */
1032
#  if defined(OBJFORMAT_ELF)
1033
   r = ocGetNames_ELF ( oc );
1034
#  elif defined(OBJFORMAT_PEi386)
1035
   r = ocGetNames_PEi386 ( oc );
1036
1037
#  elif defined(OBJFORMAT_MACHO)
   r = ocGetNames_MachO ( oc );
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
#  else
   barf("loadObj: no getNames method");
#  endif
   if (!r) { return r; }

   /* loaded, but not resolved yet */
   oc->status = OBJECT_LOADED;

   return 1;
}

/* -----------------------------------------------------------------------------
 * resolve all the currently unlinked objects in memory
 *
 * Returns: 1 if ok, 0 on error.
 */
1054
HsInt
1055
1056
1057
1058
1059
resolveObjs( void )
{
    ObjectCode *oc;
    int r;

1060
1061
    initLinker();

1062
1063
    for (oc = objects; oc; oc = oc->next) {
	if (oc->status != OBJECT_RESOLVED) {
1064
#           if defined(OBJFORMAT_ELF)
1065
	    r = ocResolve_ELF ( oc );
1066
#           elif defined(OBJFORMAT_PEi386)
1067
	    r = ocResolve_PEi386 ( oc );
1068
1069
#           elif defined(OBJFORMAT_MACHO)
	    r = ocResolve_MachO ( oc );
1070
#           else
1071
	    barf("resolveObjs: not implemented on this platform");
1072
#           endif
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
	    if (!r) { return r; }
	    oc->status = OBJECT_RESOLVED;
	}
    }
    return 1;
}

/* -----------------------------------------------------------------------------
 * delete an object from the pool
 */
HsInt
unloadObj( char *path )
{
1086
    ObjectCode *oc, *prev;
1087

1088
1089
1090
    ASSERT(symhash != NULL);
    ASSERT(objects != NULL);

1091
1092
    initLinker(); 

1093
1094
    prev = NULL;
    for (oc = objects; oc; prev = oc, oc = oc->next) {
1095
1096
1097
1098
1099
	if (!strcmp(oc->fileName,path)) {

	    /* Remove all the mappings for the symbols within this
	     * object..
	     */
1100
	    {
1101
1102
1103
1104
1105
1106
1107
                int i;
                for (i = 0; i < oc->n_symbols; i++) {
                   if (oc->symbols[i] != NULL) {
                       removeStrHashTable(symhash, oc->symbols[i], NULL);
                   }
                }
            }
1108

1109
1110
1111
1112
1113
1114
	    if (prev == NULL) {
		objects = oc->next;
	    } else {
		prev->next = oc->next;
	    }

1115
1116
	    /* We're going to leave this in place, in case there are
	       any pointers from the heap into it: */
sof's avatar
sof committed
1117
1118
1119
1120
	    /* stgFree(oc->image); */
	    stgFree(oc->fileName);
	    stgFree(oc->symbols);
	    stgFree(oc->sections);
1121
1122
1123
	    /* The local hash table should have been freed at the end
               of the ocResolve_ call on it. */
            ASSERT(oc->lochash == NULL);
sof's avatar
sof committed
1124
	    stgFree(oc);
1125
1126
1127
	    return 1;
	}
    }
1128

1129
1130
1131
1132
    belch("unloadObj: can't find `%s' to unload", path);
    return 0;
}

1133
1134
1135
1136
1137
1138
1139
/* -----------------------------------------------------------------------------
 * Sanity checking.  For each ObjectCode, maintain a list of address ranges
 * which may be prodded during relocation, and abort if we try and write
 * outside any of these.
 */
static void addProddableBlock ( ObjectCode* oc, void* start, int size )
{
1140
   ProddableBlock* pb
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
      = stgMallocBytes(sizeof(ProddableBlock), "addProddableBlock");
   /* fprintf(stderr, "aPB %p %p %d\n", oc, start, size); */
   ASSERT(size > 0);
   pb->start      = start;
   pb->size       = size;
   pb->next       = oc->proddables;
   oc->proddables = pb;
}

static void checkProddableBlock ( ObjectCode* oc, void* addr )
{
   ProddableBlock* pb;
   for (pb = oc->proddables; pb != NULL; pb = pb->next) {
      char* s = (char*)(pb->start);
      char* e = s + pb->size - 1;
      char* a = (char*)addr;
      /* Assumes that the biggest fixup involves a 4-byte write.  This
         probably needs to be changed to 8 (ie, +7) on 64-bit
         plats. */
      if (a >= s && (a+3) <= e) return;
   }
   barf("checkProddableBlock: invalid fixup in runtime linker");
}

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
/* -----------------------------------------------------------------------------
 * Section management.
 */
static void addSection ( ObjectCode* oc, SectionKind kind,
                         void* start, void* end )
{
   Section* s   = stgMallocBytes(sizeof(Section), "addSection");
   s->start     = start;
   s->end       = end;
   s->kind      = kind;
   s->next      = oc->sections;
   oc->sections = s;
1177
1178
1179
   /*
   fprintf(stderr, "addSection: %p-%p (size %d), kind %d\n",
                   start, ((char*)end)-1, end - start + 1, kind );
1180
   */
1181
1182
1183
}


1184

1185
/* --------------------------------------------------------------------------
1186
 * PEi386 specifics (Win32 targets)
1187
1188
 * ------------------------------------------------------------------------*/

1189
1190
/* The information for this linker comes from
      Microsoft Portable Executable
1191
1192
1193
      and Common Object File Format Specification
      revision 5.1 January 1998
   which SimonM says comes from the MS Developer Network CDs.
1194
1195

   It can be found there (on older CDs), but can also be found
sof's avatar
sof committed
1196
1197
1198
1199
1200
1201
1202
1203
   online at:

      http://www.microsoft.com/hwdev/hardware/PECOFF.asp

   (this is Rev 6.0 from February 1999).

   Things move, so if that fails, try searching for it via

1204
      http://www.google.com/search?q=PE+COFF+specification
sof's avatar
sof committed
1205

1206
   The ultimate reference for the PE format is the Winnt.h
sof's avatar
sof committed
1207
1208
   header file that comes with the Platform SDKs; as always,
   implementations will drift wrt their documentation.
1209

sof's avatar
sof committed
1210
1211
1212
1213
   A good background article on the PE format is Matt Pietrek's
   March 1994 article in Microsoft System Journal (MSJ)
   (Vol.9, No. 3): "Peering Inside the PE: A Tour of the
   Win32 Portable Executable File Format." The info in there
1214
   has recently been updated in a two part article in
sof's avatar
sof committed
1215
1216
1217
1218
1219
1220
   MSDN magazine, issues Feb and March 2002,
   "Inside Windows: An In-Depth Look into the Win32 Portable
   Executable File Format"

   John Levine's book "Linkers and Loaders" contains useful
   info on PE too.
1221
*/
1222

1223

1224
#if defined(OBJFORMAT_PEi386)
1225
1226
1227
1228
1229
1230
1231
1232
1233



typedef unsigned char  UChar;
typedef unsigned short UInt16;
typedef unsigned int   UInt32;
typedef          int   Int32;


1234
typedef
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
   struct {
      UInt16 Machine;
      UInt16 NumberOfSections;
      UInt32 TimeDateStamp;
      UInt32 PointerToSymbolTable;
      UInt32 NumberOfSymbols;
      UInt16 SizeOfOptionalHeader;
      UInt16 Characteristics;
   }
   COFF_header;

#define sizeof_COFF_header 20


1249
typedef
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
   struct {
      UChar  Name[8];
      UInt32 VirtualSize;
      UInt32 VirtualAddress;
      UInt32 SizeOfRawData;
      UInt32 PointerToRawData;
      UInt32 PointerToRelocations;
      UInt32 PointerToLinenumbers;
      UInt16 NumberOfRelocations;
      UInt16 NumberOfLineNumbers;
1260
      UInt32 Characteristics;
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
   }
   COFF_section;

#define sizeof_COFF_section 40


typedef
   struct {
      UChar  Name[8];
      UInt32 Value;
      UInt16 SectionNumber;
      UInt16 Type;
      UChar  StorageClass;
      UChar  NumberOfAuxSymbols;
   }
   COFF_symbol;

#define sizeof_COFF_symbol 18


typedef
   struct {
      UInt32 VirtualAddress;
      UInt32 SymbolTableIndex;
      UInt16 Type;
   }
   COFF_reloc;

#define sizeof_COFF_reloc 10


/* From PE spec doc, section 3.3.2 */
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
/* Note use of MYIMAGE_* since IMAGE_* are already defined in
   windows.h -- for the same purpose, but I want to know what I'm
   getting, here. */
#define MYIMAGE_FILE_RELOCS_STRIPPED     0x0001
#define MYIMAGE_FILE_EXECUTABLE_IMAGE    0x0002
#define MYIMAGE_FILE_DLL                 0x2000
#define MYIMAGE_FILE_SYSTEM              0x1000
#define MYIMAGE_FILE_BYTES_REVERSED_HI   0x8000
#define MYIMAGE_FILE_BYTES_REVERSED_LO   0x0080
#define MYIMAGE_FILE_32BIT_MACHINE       0x0100
1303
1304

/* From PE spec doc, section 5.4.2 and 5.4.4 */
1305
1306
1307
#define MYIMAGE_SYM_CLASS_EXTERNAL       2
#define MYIMAGE_SYM_CLASS_STATIC         3
#define MYIMAGE_SYM_UNDEFINED            0
1308
1309

/* From PE spec doc, section 4.1 */
1310
1311
#define MYIMAGE_SCN_CNT_CODE             0x00000020
#define MYIMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
sof's avatar
sof committed
1312
#define MYIMAGE_SCN_LNK_NRELOC_OVFL      0x01000000
1313
1314

/* From PE spec doc, section 5.2.1 */
1315
1316
#define MYIMAGE_REL_I386_DIR32           0x0006
#define MYIMAGE_REL_I386_REL32           0x0014
1317
1318
1319
1320


/* We use myindex to calculate array addresses, rather than
   simply doing the normal subscript thing.  That's because
1321
   some of the above structs have sizes which are not
1322
1323
1324
1325
1326
1327
   a whole number of words.  GCC rounds their sizes up to a
   whole number of words, which means that the address calcs
   arising from using normal C indexing or pointer arithmetic
   are just plain wrong.  Sigh.
*/
static UChar *
1328
myindex ( int scale, void* base, int index )
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
{
   return
      ((UChar*)base) + scale * index;
}


static void
printName ( UChar* name, UChar* strtab )
{
   if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
      UInt32 strtab_offset = * (UInt32*)(name+4);
      fprintf ( stderr, "%s", strtab + strtab_offset );
   } else {
      int i;
      for (i = 0; i < 8; i++) {
         if (name[i] == 0) break;
         fprintf ( stderr, "%c", name[i] );
      }
   }
}


static void
copyName ( UChar* name, UChar* strtab, UChar* dst, int dstSize )
{
   if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
      UInt32 strtab_offset = * (UInt32*)(name+4);
      strncpy ( dst, strtab+strtab_offset, dstSize );
      dst[dstSize-1] = 0;
   } else {
      int i = 0;
      while (1) {
         if (i >= 8) break;
         if (name[i] == 0) break;
         dst[i] = name[i];
         i++;
      }
      dst[i] = 0;
   }
}


static UChar *
cstring_from_COFF_symbol_name ( UChar* name, UChar* strtab )
{
   UChar* newstr;
   /* If the string is longer than 8 bytes, look in the