2 ** $VER: libheader.c 37.15 (14.8.97)
4 ** This file must be compiled and must be passed as the first
5 ** object to link to the linker.
7 ** (C) Copyright 1996-97 Andreas R. Kleinert
8 ** All Rights Reserved.
11 #define __USE_SYSBASE /* perhaps only recognized by SAS/C */
13 #include <exec/types.h>
14 #include <exec/memory.h>
15 #include <exec/libraries.h>
16 #include <exec/execbase.h>
17 #include <exec/resident.h>
18 #include <exec/initializers.h>
21 #include <pragma/exec_lib.h>
22 #include <linkerfunc.h>
24 #include <proto/exec.h> /* all other compilers */
26 #include <libcore/compiler.h>
27 #include <libcore/base.h>
29 #ifndef LC_LIBHEADERTYPEPTR
30 # define LC_LIBHEADERTYPEPTR struct LibHeader *
33 # define LC_LIB_FIELD(libBase) (libBase)->lh_LibNode
35 #ifndef LC_SYSBASE_FIELD
36 # define LC_SYSBASE_FIELD(libBase) (libBase)->lh_SysBase
38 #ifndef LC_SEGLIST_FIELD
39 # define LC_SEGLIST_FIELD(libBase) (libBase)->lh_SegList
41 #ifndef LC_RESIDENTNAME
42 # define LC_RESIDENTNAME LC_BUILDNAME(ROMTag)
44 #ifndef LC_RESIDENTPRI
45 # define LC_RESIDENTPRI 0
47 #ifndef LC_RESIDENTFLAGS
49 # define LC_RESIDENTFLAGS RTF_PPC | RTF_AUTOINIT
51 # define LC_RESIDENTFLAGS RTF_AUTOINIT
54 #ifndef LC_LIBBASESIZE
55 # define LC_LIBBASESIZE sizeof (struct LibHeader)
57 /* If the file with the #defines for this library is not "libdefs.h",
58 then you can redefine it. */
59 #ifndef LC_LIBDEFS_FILE
60 # define LC_LIBDEFS_FILE "libdefs.h"
63 /* Include the file with the #defines for this library */
64 #include LC_LIBDEFS_FILE
66 /* -----------------------------------------------------------------------
69 If someone tries to start a library as an executable, it must return
70 (LONG) -1 as result. That's what we are doing here.
71 ----------------------------------------------------------------------- */
74 /* FIXME: egcs 1.1b and possibly other incarnations of gcc have
75 * two nasty problems with entry() that prevents using the
76 * C version of this function on AROS 68k native.
78 * First of all, if inlining is active (-O3), the optimizer will decide
79 * that entry() is simple enough to be inlined, and it doesn't generate
80 * its code until all other functions have been compiled. Delaying asm
81 * output for a global (non static) function is probably silly because
82 * the optimizer can't eliminate its stand alone istance anyway.
84 * The second problem is that even without inlining, the code generator
85 * adds a nop instruction immediately after rts. This is probably done
86 * to help the 68040/60 pipelines, but it adds two more bytes before the
87 * library resident tag, which causes all kinds of problems on native
90 * The workaround is to embed the required assembler instructions
91 * (moveq #-1,d0 ; rts) in a constant variable.
93 #if (defined(__mc68000__) && (AROS_FLAVOUR & AROS_FLAVOUR_NATIVE))
94 const LONG entry
= 0x70FF4E75;
96 LONG ASM
LC_BUILDNAME(entry
) (void)
102 /* Predeclarations */
103 extern const int LIBEND
; /* The end of the library */
104 extern const APTR LIBFUNCTABLE
[]; /* The function table */
105 static const struct InitTable
LC_BUILDNAME(InitTab
);
106 static const struct DataTable
LC_BUILDNAME(DataTab
);
108 extern const char ALIGNED
LC_BUILDNAME(LibName
) [];
109 extern const char ALIGNED
LC_BUILDNAME(LibID
) [];
110 extern const char ALIGNED
LC_BUILDNAME(Copyright
) [];
113 LC_LIBHEADERTYPEPTR
LC_BUILDNAME(LIB_InitLib
)(LC_LIBHEADERTYPEPTR lh
, BPTR segList
, struct ExecBase
*sysBase
);
115 AROS_LD2 (LC_LIBHEADERTYPEPTR
, LC_BUILDNAME(InitLib
),
116 AROS_LDA(LC_LIBHEADERTYPEPTR
, lh
, D0
),
117 AROS_LDA(BPTR
, segList
, A0
),
118 struct ExecBase
*, sysBase
, 0, LibHeader
121 AROS_LD1 (BPTR
, LC_BUILDNAME(ExpungeLib
),
122 AROS_LDA(LC_LIBHEADERTYPEPTR
, lh
, D0
),
123 struct ExecBase
*, sysBase
, 0, LibHeader
126 /* -------------------------------------------------------------------------
127 ROMTag and Library inilitalization structure:
129 Below you find the ROMTag, which is the most important "magic" part of
130 a library (as for any other resident module). You should not need to
131 modify any of the structures directly, since all the data is referenced
132 from constants from somewhere else.
134 You may place the ROMTag directly after the LibStart (-> StartUp.c)
137 EndResident can be placed somewhere else - but it must follow the
138 ROMTag and it must not be placed in a different SECTION.
139 ------------------------------------------------------------------------- */
140 struct Resident
const ALIGNED LC_RESIDENTNAME
=
142 RTC_MATCHWORD
, /* This is a romtag */
143 (struct Resident
*)&LC_RESIDENTNAME
,
149 (char *) &LC_BUILDNAME(LibName
)[0],
150 (char *) &LC_BUILDNAME(LibID
)[6],
151 (APTR
) &LC_BUILDNAME(InitTab
)
154 static struct InitTable
/* do not change */
157 const APTR
*FunctionTable
;
158 const struct DataTable
*DataTable
;
163 const LC_BUILDNAME(InitTab
) =
170 &LC_BUILDNAME(DataTab
),
172 (APTR
) AROS_SLIB_ENTRY(LC_BUILDNAME(InitLib
), LibHeader
)
176 static struct DataTable
/* do not change */
178 UWORD ln_Type_Init
; UWORD ln_Type_Offset
; UWORD ln_Type_Content
;
179 UBYTE ln_Name_Init
; UBYTE ln_Name_Offset
; ULONG ln_Name_Content
;
180 UWORD lib_Flags_Init
; UWORD lib_Flags_Offset
; UWORD lib_Flags_Content
;
181 UWORD lib_Version_Init
; UWORD lib_Version_Offset
; UWORD lib_Version_Content
;
182 UWORD lib_Revision_Init
; UWORD lib_Revision_Offset
; UWORD lib_Revision_Content
;
183 UBYTE lib_IdString_Init
; UBYTE lib_IdString_Offset
; ULONG lib_IdString_Content
;
186 const LC_BUILDNAME(DataTab
) =
188 INITBYTE(OFFSET(Node
, ln_Type
), NT_TYPE
),
189 0x80, (UBYTE
) OFFSET(Node
, ln_Name
), (ULONG
) &LC_BUILDNAME(LibName
[0]),
190 INITBYTE(OFFSET(Library
, lib_Flags
), LIBF_SUMUSED
|LIBF_CHANGED
),
191 INITWORD(OFFSET(Library
, lib_Version
), VERSION_NUMBER
),
192 INITWORD(OFFSET(Library
, lib_Revision
), REVISION_NUMBER
),
193 0x80, (UBYTE
) OFFSET(Library
, lib_IdString
), (ULONG
) &LC_BUILDNAME(LibID
)[0],
198 const char ALIGNED
LC_BUILDNAME(LibName
) [] = NAME_STRING
;
199 const char ALIGNED
LC_BUILDNAME(LibID
) [] = VERSION_STRING
;
200 const char ALIGNED
LC_BUILDNAME(Copyright
) [] = COPYRIGHT_STRING
;
202 /* Use supplied functions to initialize the non-standard parts of the
204 #ifndef LC_NO_INITLIB
205 # ifdef LC_STATIC_INITLIB
208 ULONG SAVEDS STDARGS
LC_BUILDNAME(L_InitLib
) (LC_LIBHEADERTYPEPTR lh
);
209 # define __L_InitLib LC_BUILDNAME(L_InitLib)
211 # define __L_InitLib(x) 1
213 #ifndef LC_NO_OPENLIB
214 # ifdef LC_STATIC_OPENLIB
217 ULONG SAVEDS STDARGS
LC_BUILDNAME(L_OpenLib
) (LC_LIBHEADERTYPEPTR lh
);
218 # define __L_OpenLib LC_BUILDNAME(L_OpenLib)
220 # define __L_OpenLib(x) 1
222 #ifndef LC_NO_CLOSELIB
223 # ifdef LC_STATIC_CLOSELIB
226 void SAVEDS STDARGS
LC_BUILDNAME(L_CloseLib
) (LC_LIBHEADERTYPEPTR lh
);
227 # define __L_CloseLib LC_BUILDNAME(L_CloseLib)
229 # define __L_CloseLib(x) /* eps */
231 #ifndef LC_NO_EXPUNGELIB
232 # ifdef LC_STATIC_EXPUNGELIB
235 void SAVEDS STDARGS
LC_BUILDNAME(L_ExpungeLib
) (LC_LIBHEADERTYPEPTR lh
);
236 # define __L_ExpungeLib LC_BUILDNAME(L_ExpungeLib)
238 # define __L_ExpungeLib(x) /* eps */
242 # define SysBase (LC_SYSBASE_FIELD(lh))
243 # define __LC_OWN_SYSBASE
246 /* -----------------------------------------------------------------------
249 This one is single-threaded by the Ramlib process. Theoretically you
250 can do, what you like here, since you have full exclusive control over
251 all the library code and data. But due to some bugs in Ramlib V37-40,
252 you can easily cause a deadlock when opening certain libraries here
253 (which open other libraries, that open other libraries, that...)
254 ----------------------------------------------------------------------- */
256 LC_LIBHEADERTYPEPTR
LC_BUILDNAME(LIB_InitLib
)(LC_LIBHEADERTYPEPTR lh
, BPTR segList
, struct ExecBase
*sysBase
)
259 AROS_LH2 (LC_LIBHEADERTYPEPTR
, LC_BUILDNAME(InitLib
),
260 AROS_LHA(LC_LIBHEADERTYPEPTR
, lh
, D0
),
261 AROS_LHA(BPTR
, segList
, A0
),
262 struct ExecBase
*, sysBase
, 0, LibHeader
267 LC_SYSBASE_FIELD(lh
) = sysBase
;
268 LC_SEGLIST_FIELD(lh
) = segList
;
270 #ifndef LC_NO_INITLIB
271 if (__L_InitLib (lh
))
277 ULONG negsize
, possize
, fullsize
;
278 UBYTE
*negptr
= (UBYTE
*) lh
;
280 negsize
= LC_LIB_FIELD(lh
).lib_NegSize
;
281 possize
= LC_LIB_FIELD(lh
).lib_PosSize
;
282 fullsize
= negsize
+ possize
;
285 FreeMem (negptr
, fullsize
);
291 #endif /* LC_NO_INITLIB */
295 /* -----------------------------------------------------------------------
298 This one is enclosed within a Forbid/Permit pair by Exec V37-40. Since
299 a Wait() call would break this Forbid/Permit(), you are not allowed to
300 start any operations that may cause a Wait() during their processing.
301 It's possible, that future OS versions won't turn the multi-tasking
302 off, but instead use semaphore protection for this function.
304 Currently you only can bypass this restriction by supplying your own
306 ----------------------------------------------------------------------- */
307 AROS_LH1 (LC_LIBHEADERTYPEPTR
, LC_BUILDNAME(OpenLib
),
308 AROS_LHA (ULONG
, version
, D0
),
309 LC_LIBHEADERTYPEPTR
, lh
, 1, LibHeader
318 if (__L_OpenLib (lh
))
321 LC_LIB_FIELD(lh
).lib_OpenCnt
++;
323 LC_LIB_FIELD(lh
).lib_OpenCnt
= 1;
324 #endif /* NOEXPUNGE */
326 LC_LIB_FIELD(lh
).lib_Flags
&= ~LIBF_DELEXP
;
336 /* -----------------------------------------------------------------------
339 This one is enclosed within a Forbid/Permit pair by Exec V37-40. Since
340 a Wait() call would break this Forbid/Permit(), you are not allowed to
341 start any operations that may cause a Wait() during their processing.
342 It's possible, that future OS versions won't turn the multi-tasking
343 off, but instead use semaphore protection for this function.
345 Currently you only can bypass this restriction by supplying your own
347 ----------------------------------------------------------------------- */
348 AROS_LH0 (BPTR
, LC_BUILDNAME(CloseLib
),
349 LC_LIBHEADERTYPEPTR
, lh
, 2, LibHeader
354 LC_LIB_FIELD(lh
).lib_OpenCnt
--;
358 if(!LC_LIB_FIELD(lh
).lib_OpenCnt
)
360 if(LC_LIB_FIELD(lh
).lib_Flags
& LIBF_DELEXP
)
362 return AROS_LC1(BPTR
, LC_BUILDNAME(ExpungeLib
),
363 AROS_LCA(LC_LIBHEADERTYPEPTR
, lh
, D0
),
364 struct ExecBase
*, SysBase
, 3, LibHeader
368 #endif /* NOEXPUNGE */
374 /* -----------------------------------------------------------------------
377 This one is enclosed within a Forbid/Permit pair by Exec V37-40. Since
378 a Wait() call would break this Forbid/Permit(), you are not allowed to
379 start any operations that may cause a Wait() during their processing.
380 It's possible, that future OS versions won't turn the multi-tasking
381 off, but instead use semaphore protection for this function.
383 Currently you only can bypass this restriction by supplying your own
384 semaphore mechanism but since expunging can't be done twice, one should
386 ----------------------------------------------------------------------- */
387 AROS_LH1 (BPTR
, LC_BUILDNAME(ExpungeLib
),
388 AROS_LHA(LC_LIBHEADERTYPEPTR
, lh
, D0
),
389 struct ExecBase
*, sysBase
, 3, LibHeader
396 if(!LC_LIB_FIELD(lh
).lib_OpenCnt
)
398 ULONG negsize
, possize
, fullsize
;
399 UBYTE
*negptr
= (UBYTE
*)lh
;
401 seglist
= LC_SEGLIST_FIELD(lh
);
403 Remove((struct Node
*)lh
);
407 negsize
= LC_LIB_FIELD(lh
).lib_NegSize
;
408 possize
= LC_LIB_FIELD(lh
).lib_PosSize
;
409 fullsize
= negsize
+ possize
;
412 FreeMem(negptr
, fullsize
);
421 LC_LIB_FIELD(lh
).lib_Flags
|= LIBF_DELEXP
;
422 #endif /* NOEXPUNGE */
428 /* -----------------------------------------------------------------------
431 This is a function which is reserved for later extension.
432 ----------------------------------------------------------------------- */
433 AROS_LH0 (LC_LIBHEADERTYPEPTR
, LC_BUILDNAME(ExtFuncLib
),
434 LC_LIBHEADERTYPEPTR
, lh
, 4, LibHeader
442 #ifdef __LC_OWN_SYSBASE
449 This is only for SAS/C - its intention is to turn off internal CTRL-C
450 handling for standard C function and to avoid calls to exit() et al.
453 #ifdef ARK_OLD_STDIO_FIX
455 ULONG XCEXIT
= NULL
; /* these symbols may be referenced by */
456 ULONG _XCEXIT
= NULL
; /* some functions of sc.lib, but should */
457 ULONG ONBREAK
= NULL
; /* never be used inside a shared library */
458 ULONG _ONBREAK
= NULL
;
461 ULONG ProgramName
= NULL
;
462 ULONG _ProgramName
= NULL
;
463 ULONG StackPtr
= NULL
;
464 ULONG _StackPtr
= NULL
;
470 #endif /* ARK_OLD_STDIO_FIX */
472 void __regargs
__chkabort(void) { } /* a shared library cannot be */
473 void __regargs
_CXBRK(void) { } /* CTRL-C aborted when doing I/O */