ObjFLoader.st
changeset 20 f8dd8ba75205
parent 19 84a1ddf215a5
child 28 a9d33ea0692d
equal deleted inserted replaced
19:84a1ddf215a5 20:f8dd8ba75205
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
    13 Object subclass:#ObjectFileLoader
    13 Object subclass:#ObjectFileLoader
    14        instanceVariableNames:''
    14        instanceVariableNames:''
    15        classVariableNames:'MySymbolTable StubNr Verbose'
    15        classVariableNames:'MySymbolTable Verbose'
    16        poolDictionaries:''
    16        poolDictionaries:''
    17        category:'System-Compiler'
    17        category:'System-Compiler'
    18 !
    18 !
    19 
    19 
    20 ObjectFileLoader comment:'
    20 ObjectFileLoader comment:'
    21 
       
    22 COPYRIGHT (c) 1993 by Claus Gittinger
    21 COPYRIGHT (c) 1993 by Claus Gittinger
    23              All Rights Reserved
    22              All Rights Reserved
    24 
       
    25 this one knowns how to load in external (c)-modules
       
    26 (see fileIn/cExample.c) it is all experimental and 
       
    27 WILL DEFINITELY change soon ...
       
    28 
       
    29 (goal is to allow loading of binary classes)
       
    30 
       
    31 $Header: /cvs/stx/stx/libcomp/Attic/ObjFLoader.st,v 1.6 1994-03-30 10:09:51 claus Exp $
       
    32 '!
    23 '!
    33 
    24 
    34 %{
    25 %{
    35 /*
    26 /*
    36  * by default, use whatever the system provides
    27  * by default, use whatever the system provides
    37  */
    28  */
    38 #ifdef sunos
    29 #ifdef sunos
    39 # define SUN_DL
    30 # define SUN_DL
       
    31 # define HAS_DL
    40 #endif
    32 #endif
    41 
    33 
    42 #ifdef NeXT
    34 #ifdef NeXT
    43 # define NEXT_DL
    35 # define NEXT_DL
       
    36 # define HAS_DL
    44 #endif
    37 #endif
    45 
    38 
    46 #ifdef SYSV4
    39 #ifdef SYSV4
    47 # define SYSV4_DL
    40 # define SYSV4_DL
       
    41 # define HAS_DL
    48 #endif
    42 #endif
    49 
    43 
    50 /*
    44 /*
    51  * but GNU_DL overwrites this
    45  * but GNU_DL overwrites this - its better
    52  */
    46  */
    53 #ifdef GNU_DL
    47 #ifdef GNU_DL
       
    48 # define HAS_DL
    54 # undef SYSV4_DL
    49 # undef SYSV4_DL
    55 # undef NEXT_DL
    50 # undef NEXT_DL
    56 # undef SUN_DL
    51 # undef SUN_DL
    57 #endif
    52 #endif
    58 
    53 
    61 #  define _RLD_H_
    56 #  define _RLD_H_
    62 #  include <rld.h>
    57 #  include <rld.h>
    63 # endif
    58 # endif
    64 #endif /* NEXT_DL */
    59 #endif /* NEXT_DL */
    65 
    60 
       
    61 #include <stdio.h>
       
    62 
       
    63 /*
       
    64  * if no dynamic link facilities, do it the hard way ...
       
    65  */
       
    66 #ifndef HAS_DL
       
    67 
       
    68 # ifdef A_DOT_OUT
       
    69 #  include <a.out.h>
       
    70 #  ifndef N_MAGIC
       
    71 #   if defined(sinix) && defined(BSD)
       
    72 #    define N_MAGIC(hdr) (hdr.a_magic & 0xFFFF)
       
    73 #   else
       
    74 #    define N_MAGIC(hdr) (hdr.a_magic)
       
    75 #   endif
       
    76 #  endif
       
    77 # endif /* a.out */
       
    78  
       
    79 # ifdef COFF
       
    80 #  ifdef mips
       
    81 #    include <sys/exec.h>
       
    82 #  else
       
    83 #    include <a.out.h>
       
    84 #  endif
       
    85 # endif /* coff */
       
    86 
       
    87 # ifdef ELF
       
    88 #  include <elf.h>
       
    89 # endif /* elf */
       
    90 
       
    91 #endif /* not HAS_DL */
       
    92 
    66 static OBJ loadAddrLow, loadAddrHi;
    93 static OBJ loadAddrLow, loadAddrHi;
    67 %}
    94 %}
    68 
    95 
       
    96 !ObjectFileLoader class methodsFor:'documentation'!
       
    97 
       
    98 copyright
       
    99 "
       
   100  COPYRIGHT (c) 1993 by Claus Gittinger
       
   101               All Rights Reserved
       
   102 
       
   103  This software is furnished under a license and may be used
       
   104  only in accordance with the terms of that license and with the
       
   105  inclusion of the above copyright notice.   This software may not
       
   106  be provided or otherwise made available to, or used by, any
       
   107  other person.  No title to or ownership of the software is
       
   108  hereby transferred.
       
   109 "
       
   110 !
       
   111 
       
   112 version
       
   113 "
       
   114 $Header: /cvs/stx/stx/libcomp/Attic/ObjFLoader.st,v 1.7 1994-06-02 20:26:03 claus Exp $
       
   115 "
       
   116 !
       
   117 
       
   118 documentation
       
   119 "
       
   120     This class knowns how to dynamically load in external object-modules.
       
   121     There are basically two totally different mechanisms to do this:
       
   122         a) if there exists some dynamic-link facility such as:
       
   123            GNU-DL, dlopen (sparc, SYS5.4), rld_open (NeXT),
       
   124            this is used
       
   125         b) if no such facility exists, the normal linker is used to
       
   126            link the module to text/data address as previously malloced,
       
   127            and the object file loaded into that space.
       
   128            
       
   129     Currently, not all mechanisms work fully satisfying.
       
   130     For example, the sun dl*-functions do an exit on link-errors (which
       
   131     is certainly not what we want here :-(; the NeXT mechanism does not
       
   132     allow for selective unloading (only all or last).
       
   133     The only really useful package is the GNU-dl package, which is only
       
   134     available for a.out file formats. (i.e. only linux people can use
       
   135     it at this time).
       
   136 "
       
   137 ! !
       
   138 
    69 !ObjectFileLoader class methodsFor:'initialization'!
   139 !ObjectFileLoader class methodsFor:'initialization'!
    70 
   140 
    71 initialize
   141 initialize
    72     "name of object file, where initial symbol table is found"
   142     "name of object file, where initial symbol table is found"
    73 
   143 
    74     MySymbolTable := 'smalltalk'.
   144     MySymbolTable := 'smalltalk'.
    75     StubNr := 1.
       
    76     Verbose := false
   145     Verbose := false
    77 !
   146 !
    78 
   147 
    79 verbose:aBoolean
   148 verbose:aBoolean
    80     "turn on/off debug traces"
   149     "turn on/off debug traces"
    85 ! !
   154 ! !
    86 
   155 
    87 !ObjectFileLoader class methodsFor:'command defaults'!
   156 !ObjectFileLoader class methodsFor:'command defaults'!
    88 
   157 
    89 needSeparateIDSpaces
   158 needSeparateIDSpaces
    90     "return true, if we need separate I and D spaces"
   159     "return true, if we need separate I and D spaces.
       
   160      This is only needed if no dynamic-link facilitiy exists."
    91 
   161 
    92     |os cpu|
   162     |os cpu|
    93 
   163 
    94     os := OperatingSystem getSystemType.
   164     os := OperatingSystem getSystemType.
    95     cpu := OperatingSystem getCPUType.
   165     cpu := OperatingSystem getCPUType.
    97     (os = 'sunos') ifTrue:[
   167     (os = 'sunos') ifTrue:[
    98         (cpu = 'sparc') ifTrue:[ ^ true ]
   168         (cpu = 'sparc') ifTrue:[ ^ true ]
    99     ].
   169     ].
   100     (os = 'linux') ifTrue:[ ^ false ].
   170     (os = 'linux') ifTrue:[ ^ false ].
   101 
   171 
   102     'dont know if we need sepId - assume no' printNewline.
   172     'dont know if we need sepId - assume no' errorPrintNL.
   103     ^ false
   173     ^ false
   104 !
   174 !
   105 
   175 
   106 absLd:file text:textAddr data:dataAddr
   176 absLd:file text:textAddr data:dataAddr
   107    "this should return a string to link file.o to absolute address"
   177    "this should return a string to link file.o to absolute address.
       
   178     This is only needed if no dynamic-link facilitiy exists."
   108 
   179 
   109     |os cpu|
   180     |os cpu|
   110 
   181 
   111     os := OperatingSystem getSystemType.
   182     os := OperatingSystem getSystemType.
   112     cpu := OperatingSystem getCPUType.
   183     cpu := OperatingSystem getCPUType.
   139     ].
   210     ].
   140     self error:'do not know how to link absolute'
   211     self error:'do not know how to link absolute'
   141 !
   212 !
   142 
   213 
   143 absLd:file text:textAddr
   214 absLd:file text:textAddr
   144    "this should return a string to link file.o to absolute address"
   215    "this should return a string to link file.o to absolute address.
       
   216     This is only needed if no dynamic-link facilitiy exists."
   145 
   217 
   146     |os cpu|
   218     |os cpu|
   147 
   219 
   148     os := OperatingSystem getSystemType.
   220     os := OperatingSystem getSystemType.
   149     cpu := OperatingSystem getCPUType.
   221     cpu := OperatingSystem getCPUType.
   161     ].
   233     ].
   162     self error:'do not know how to link absolute'
   234     self error:'do not know how to link absolute'
   163 
   235 
   164 ! !
   236 ! !
   165 
   237 
   166 !ObjectFileLoader class methodsFor:'dynamic loading'!
       
   167 
       
   168 loadFile:aFileName library:librariesString withBindings:bindings in:aClass
       
   169     "first, load the file itself"
       
   170 
       
   171     (self loadFile:aFileName with:librariesString) ifFalse:[^ false].
       
   172 
       
   173     "then, create stubs"
       
   174     self bindExternalFunctions:bindings in:aClass
       
   175 !
       
   176 
       
   177 loadFile:aFileName withBindings:bindings in:aClass
       
   178     "load an object file containing external functions, and bind the functions as described 
       
   179      in bindings, which is an Array of
       
   180         (selector functionName argTypes returnType)
       
   181      entries, example:
       
   182      #(
       
   183         (sel1:and: 'f1' (SmallInteger SmallInteger)    nil)   -> bind 'aClass sel1:and:' to: 'void f1(int, int)'
       
   184         (sel2:and: 'f2' (String SmallInteger)       String)   -> bind 'aClass sel2:and:' to: 'char *f2(char *, int)'
       
   185       )
       
   186     "
       
   187 
       
   188     "first, load the file itself"
       
   189 
       
   190     (self loadFile:aFileName) ifFalse:[^ false].
       
   191 
       
   192     "then, create stubs"
       
   193     self bindExternalFunctions:bindings in:aClass
       
   194 !
       
   195 
       
   196 bindExternalFunctions:bindings in:aClass
       
   197     | selector functionName argTypes returnType allOk |
       
   198 
       
   199     allOk := true.
       
   200     bindings do:[:aBinding |
       
   201         selector := aBinding at:1.
       
   202         functionName := aBinding at:2.
       
   203         argTypes := aBinding at:3.
       
   204         returnType := aBinding at:4.
       
   205         (self createStubFor:selector calling:functionName args:argTypes returning:returnType in:aClass)
       
   206         isNil ifTrue:[
       
   207             Transcript showCr:'binding of ' , functionName , ' failed.'.
       
   208             allOk := false
       
   209         ]
       
   210     ].
       
   211     ^ allOk
       
   212 ! !
       
   213 
       
   214 !ObjectFileLoader class methodsFor:'creating stubs'!
       
   215 
       
   216 storeGlobalAddressesOn:aStream
       
   217 
       
   218     Smalltalk allKeysDo:[:key |
       
   219         self storeGlobalAddressOf:key on:aStream
       
   220     ]
       
   221 
       
   222     "ObjectFileLoader storeGlobalAddressesOn:Transcript"
       
   223     "|f|
       
   224      f := FileStream newFileNamed:'syms.c'.
       
   225      ObjectFileLoader storeGlobalAddressesOn:f.
       
   226      f close"
       
   227 !
       
   228 
       
   229 storeGlobalAddressOf:aSymbol on:aStream
       
   230     |globalName|
       
   231 
       
   232     globalName := aSymbol asString.
       
   233     (globalName includes:$:) ifTrue:[
       
   234         globalName replaceAll:$: by:$_
       
   235     ].
       
   236 
       
   237     aStream nextPutAll:'#define ',globalName,'_addr '.
       
   238     aStream nextPutAll:(Smalltalk cellAt:aSymbol) printString.
       
   239     aStream cr.
       
   240 
       
   241     aStream nextPutAll:'#define ',globalName,' ( *( (OBJ *) ',globalName,'_addr))'.
       
   242     aStream cr
       
   243 
       
   244     "ObjectFileLoader storeGlobalAddressOf:#String on:Transcript"
       
   245     "ObjectFileLoader storeGlobalAddressOf:#Symbol on:Transcript"
       
   246 !
       
   247 
       
   248 createStubFor:aSelector calling:functionName args:argTypes returning:returnType in:aClass
       
   249     "create a method calling a stub function"
       
   250 
       
   251     |address newMethod s|
       
   252 
       
   253     address := self createStubCalling:functionName args:argTypes returning:returnType.
       
   254     address isNil ifTrue:[^ nil].
       
   255 
       
   256     newMethod := Method new.
       
   257     newMethod code:address.
       
   258     newMethod category:'external functions'.
       
   259     s := '"calls external function 
       
   260 
       
   261 ' , (self cTypeFor:returnType) , ' ' , functionName , '( '.
       
   262     argTypes notNil ifTrue:[
       
   263         argTypes do:[:type |
       
   264             s := s , (self cTypeFor:type) , ' '
       
   265         ]
       
   266     ].
       
   267     s := s , ')
       
   268 "'.
       
   269     newMethod source:s.
       
   270     newMethod numberOfMethodVars:0.
       
   271     newMethod stackSize:0.
       
   272 
       
   273     aClass class addSelector:aSelector withMethod:newMethod.
       
   274 
       
   275     SilentLoading ifFalse:[
       
   276         Transcript showCr:('created stub: ',aClass class name,' ', aSelector)
       
   277     ].
       
   278 
       
   279     ^ newMethod
       
   280 
       
   281     "ObjectFileLoader createStubFor:#printf: 
       
   282                             calling:'printf' 
       
   283                                args:#(String) 
       
   284                           returning:nil 
       
   285                                  in:TestClass"
       
   286     "ObjectFileLoader createStubFor:#printf:with:
       
   287                             calling:'printf' 
       
   288                                args:#(String SmallInteger)
       
   289                           returning:nil 
       
   290                                  in:TestClass"
       
   291 !
       
   292 
       
   293 createStubCalling:functionName args:argTypes returning:returnType
       
   294     "create a stub function for calling functionName - return the address of the
       
   295      function in core or nil on error"
       
   296 
       
   297     |baseName p t l handle address stubName|
       
   298 
       
   299     stubName := 'stub000' , (StubNr printStringRadix:16).
       
   300     stubName := stubName copyFrom:(stubName size - 7).
       
   301 
       
   302     baseName := self createStubSource:stubName calling:functionName args:argTypes returning:returnType.
       
   303     baseName isNil ifTrue:[^ nil].
       
   304 
       
   305     "compile it ..."
       
   306     Verbose ifTrue:[
       
   307         Transcript showCr:'compiling stub ...', baseName. Transcript endEntry
       
   308     ].
       
   309 
       
   310     (OperatingSystem executeCommand:('make /tmp/' , baseName , '.o')) ifFalse:[
       
   311         Transcript showCr:'compilation error.'.
       
   312         ^ nil
       
   313     ].
       
   314     OperatingSystem executeCommand:('mv ' , baseName , '.o /tmp/' , baseName , '.o').
       
   315     Verbose ifFalse:[
       
   316         OperatingSystem executeCommand:('rm /tmp/' , baseName , '.c').
       
   317     ].
       
   318 
       
   319     (OperatingSystem getOSType = 'sys5.4') ifTrue:[
       
   320         "make it a sharable object"
       
   321 
       
   322         Verbose ifTrue:[
       
   323             Transcript showCr:'makeing shared object stub ...', baseName. Transcript endEntry.
       
   324         ].
       
   325         OperatingSystem executeCommand:('ld -G -o /tmp/',baseName,'.so /tmp/',baseName,'.o').
       
   326 
       
   327         "attach to it"
       
   328         handle := self openDynamicObject:('/tmp/',baseName,'.so').
       
   329         handle isNil ifTrue:[
       
   330             Transcript showCr:('dlopen error:', '/tmp/',baseName,'.so').
       
   331             ^ nil
       
   332         ].
       
   333         "find the stubs address"
       
   334         address := self getSymbol:stubName from:handle.
       
   335         address isNil ifTrue:[
       
   336             Transcript showCr:'dlsym failed'.
       
   337              ^ nil
       
   338         ]
       
   339     ].
       
   340 
       
   341     ((OperatingSystem getOSType = 'sunos') 
       
   342      or:[OperatingSystem getOSType = 'linux']) ifTrue:[
       
   343         "load it"
       
   344         (self loadFile:('/tmp/' , baseName , '.o')) ifFalse:[
       
   345             Transcript showCr:'load error.'.
       
   346             ^ nil
       
   347         ].
       
   348 
       
   349         "find the stubs address (use nm to get the address)"
       
   350         t := Text new.
       
   351         p := PipeStream readingFrom:('nm SymbolTable|grep ' , stubName , ' |grep T').
       
   352         [p atEnd] whileFalse:[
       
   353             l := p nextLine.
       
   354             l notNil ifTrue:[
       
   355                 t add:l
       
   356             ]
       
   357         ].
       
   358         p close.
       
   359         (t size == 1) ifFalse:[
       
   360             Transcript showCr:('oops, ' , stubName , ' not in name-list.').
       
   361             ^ nil
       
   362         ].
       
   363         address := Integer readFrom:(ReadStream on:(t at:1)) radix:16
       
   364     ].
       
   365 
       
   366     address isNil ifTrue:[
       
   367         Transcript showCr:'no way to dynamically load objects'.
       
   368         ^ nil
       
   369     ].
       
   370 
       
   371     Verbose ifTrue:[
       
   372         Transcript show:'stub ' , stubName , ' address:'.
       
   373         Transcript showCr:(address printStringRadix:16).
       
   374     ].
       
   375 
       
   376     StubNr := StubNr + 1.
       
   377     ^ address
       
   378 
       
   379     "ObjectFileLoader createStubCalling:'printf' args:#(String) returning:nil"
       
   380 !
       
   381 
       
   382 createStubSource:stubName calling:functionName args:argTypes returning:returnType
       
   383     "create a temp file with stub-code - return base-filename or nil"
       
   384 
       
   385     |pid baseName index aStream argName|
       
   386 
       
   387     pid := OperatingSystem getProcessId printString.
       
   388     baseName := 'stc' ,  pid.
       
   389     aStream := FileStream newFileNamed:('/tmp/' , baseName , '.c').
       
   390     aStream nextPutAll:'
       
   391 #include <stc.h>
       
   392 '.
       
   393 
       
   394     OperatingSystem getOSType = 'sys5.4' ifTrue:[
       
   395         self storeGlobalAddressesOn:aStream.
       
   396     ].
       
   397 
       
   398     aStream nextPutAll:'
       
   399 ' , stubName , '(self, __sel, SND_COMMA __srch, __pI,
       
   400                  __a1, __a2, __a3, __a4, __a5, __a6, __a7, __a8)
       
   401     OBJ __a1, __a2, __a3, __a4, __a5, __a6, __a7, __a8;
       
   402     OBJ __sel, __srch;
       
   403     SENDER_DECL
       
   404 {
       
   405     extern OBJ _ISKINDOF_(), ExternalStream;
       
   406 '.
       
   407 
       
   408     returnType notNil ifTrue:[
       
   409         aStream nextPutAll:'    '.
       
   410         aStream nextPutAll:(self cTypeFor:returnType).
       
   411         aStream nextPutAll:' __ret;'.
       
   412         aStream cr
       
   413     ].
       
   414 
       
   415     "gen type checking code"
       
   416     argTypes notNil ifTrue:[
       
   417         index := 0.
       
   418         argTypes do:[:argType |
       
   419             (index + 1) timesRepeat:[ aStream nextPutAll:'    '].
       
   420             argName := '__a' , (index + 1) printString.
       
   421             aStream nextPutAll:'if ('.
       
   422             (self checkType:argType name:argName on:aStream) ifFalse:[^ nil].
       
   423             aStream nextPutAll:') {'.
       
   424             aStream cr.
       
   425             index := index + 1
       
   426         ]
       
   427     ].
       
   428     "call the function"
       
   429 
       
   430     (index + 1) timesRepeat:[ aStream nextPutAll:'    '].
       
   431     returnType notNil ifTrue:[
       
   432         aStream nextPutAll:'__ret = '
       
   433     ].
       
   434     aStream nextPutAll:functionName , '('.
       
   435     argTypes notNil ifTrue:[
       
   436         index := 0.
       
   437         argTypes do:[:argType |
       
   438             argName := '__a' , (index + 1) printString.
       
   439             self convertStToC:argType name:argName on:aStream.
       
   440             index := index + 1.
       
   441             (index == argTypes size) ifFalse:[
       
   442                 aStream nextPutAll:','
       
   443             ]
       
   444         ]
       
   445     ].
       
   446     aStream nextPutAll:');'. aStream cr.
       
   447 
       
   448     argTypes notNil ifTrue:[
       
   449         argTypes size timesRepeat:[
       
   450             index timesRepeat:[ aStream nextPutAll:'    '].
       
   451             aStream nextPutAll:'}'. aStream cr.
       
   452             index := index - 1
       
   453         ]
       
   454     ].
       
   455 
       
   456     returnType notNil ifTrue:[
       
   457         aStream nextPutAll:'    return '.
       
   458         self convertCToSt:returnType name:'__ret' on:aStream.
       
   459         aStream nextPutAll:';'
       
   460     ] ifFalse:[
       
   461         aStream nextPutAll:'    return self;'
       
   462     ].
       
   463     aStream cr.
       
   464 
       
   465     aStream nextPutAll:'}'. aStream cr.
       
   466     aStream close.
       
   467     ^ baseName
       
   468 
       
   469     "ObjectFileLoader createStubSource:'stub1' calling:'printMessage'  args:#(String) returning:nil"
       
   470     "ObjectFileLoader createStubSource:'stub2' calling:'printMessage2' args:#(String SmallInteger) returning:#String"
       
   471     "ObjectFileLoader createStubSource:'stub3' calling:'sqrt'          args:#(Float) returning:#Float"
       
   472     "ObjectFileLoader createStubSource:'stub4' calling:'checking'      args:#(SmallInteger SmallInteger) returning:#Boolean"
       
   473     "ObjectFileLoader createStubSource:'stub5' calling:'fprintf'       args:#(ExternalStream  String) returning:#SmallInteger"
       
   474 !
       
   475 
       
   476 checkType:argType name:argName on:aStream
       
   477     "generate type checking code"
       
   478 
       
   479     (argType == #SmallInteger) ifTrue:[
       
   480         aStream nextPutAll:'_isSmallInteger(' , argName , ')'.
       
   481         ^ true
       
   482     ].
       
   483     (argType == #Float) ifTrue:[
       
   484         aStream nextPutAll:'__isFloat(' , argName , ')'.
       
   485         ^ true
       
   486     ].
       
   487     (argType == #Character) ifTrue:[
       
   488         aStream nextPutAll:'__isCharacter(' , argName , ')'.
       
   489         ^ true
       
   490     ].
       
   491     (argType == #String) ifTrue:[
       
   492         aStream nextPutAll:'__isString(' , argName , ')'.
       
   493         ^ true
       
   494     ].
       
   495     (argType == #Symbol) ifTrue:[
       
   496         aStream nextPutAll:'__isSymbol(' , argName , ')'.
       
   497         ^ true
       
   498     ].
       
   499     (argType == #Boolean) ifTrue:[
       
   500         aStream nextPutAll:'((' , argName , '==true)'.
       
   501         aStream nextPutAll:'||(' , argName , '==false))'.
       
   502         ^ true
       
   503     ].
       
   504     (argType == #ByteArray) ifTrue:[
       
   505         aStream nextPutAll:'__isByteArray(' , argName , ')'.
       
   506         ^ true
       
   507     ].
       
   508     (argType == #ExternalStream) ifTrue:[
       
   509         aStream nextPutAll:'(_ISKINDOF_(' , argName , ', SND_COMMA ExternalStream)==true)'.
       
   510         ^ true
       
   511     ].
       
   512     self error:'argType ' , argType, ' not (yet) supported'.
       
   513     ^ false
       
   514 !
       
   515 
       
   516 convertStToC:stType name:argName on:aStream
       
   517     "generate type conversion code"
       
   518 
       
   519     |idx|
       
   520 
       
   521     (stType == #SmallInteger) ifTrue:[
       
   522         aStream nextPutAll:'_intVal(' , argName , ')'.
       
   523         ^ true
       
   524     ].
       
   525     (stType == #Float) ifTrue:[
       
   526         aStream nextPutAll:'_floatVal(' , argName , ')'.
       
   527         ^ true
       
   528     ].
       
   529     (stType == #Character) ifTrue:[
       
   530         aStream nextPutAll:'_characterVal(' , argName , ')'.
       
   531         ^ true
       
   532     ].
       
   533     (stType == #String) ifTrue:[
       
   534         aStream nextPutAll:'_stringVal(' , argName , ')'.
       
   535         ^ true
       
   536     ].
       
   537     (stType == #Symbol) ifTrue:[
       
   538         aStream nextPutAll:'_stringVal(' , argName , ')'.
       
   539         ^ true
       
   540     ].
       
   541     (stType == #Boolean) ifTrue:[
       
   542         aStream nextPutAll:'((' , argName , '==true) ? 1 : 0)'.
       
   543         ^ true
       
   544     ].
       
   545     (stType == #ByteArray) ifTrue:[
       
   546         aStream nextPutAll:'(_ByteArrayInstPtr(' , argName , ')->ba_element)'.
       
   547         ^ true
       
   548     ].
       
   549     (stType == #ExternalStream) ifTrue:[
       
   550         "find the file-pointer inst-var"
       
   551         idx := (ExternalStream allInstVarNames indexOf:'filePointer').
       
   552         aStream nextPutAll:'_intVal(_InstPtr(' , argName , ')->i_instvars['.
       
   553         aStream nextPutAll:(idx - 1) printString, '])'.
       
   554         ^ true
       
   555     ].
       
   556     ^ false
       
   557 !
       
   558 
       
   559 convertCToSt:stType name:argName on:aStream
       
   560     "generate type conversion code"
       
   561 
       
   562     (stType == #SmallInteger) ifTrue:[
       
   563         aStream nextPutAll:'_MKSMALLINT(' , argName , ')'.
       
   564         ^ true
       
   565     ].
       
   566     (stType == #Float) ifTrue:[
       
   567         aStream nextPutAll:'_MKFLOAT(' , argName , ' COMMA_SND)'.
       
   568         ^ true
       
   569     ].
       
   570     (stType == #Character) ifTrue:[
       
   571         aStream nextPutAll:'_MKCHARACTER(' , argName , ')'.
       
   572         ^ true
       
   573     ].
       
   574     (stType == #String) ifTrue:[
       
   575         aStream nextPutAll:'(' , argName , ' ? _MKSTRING(' , argName , ' COMMA_SND) : nil)'.
       
   576         ^ true
       
   577     ].
       
   578     (stType == #Symbol) ifTrue:[
       
   579         aStream nextPutAll:'(' , argName , ' ? _MKSYMBOL(' , argName , ' COMMA_SND) : nil)'.
       
   580         ^ true
       
   581     ].
       
   582     (stType == #Boolean) ifTrue:[
       
   583         aStream nextPutAll:'(' , argName , ' ? true : false)'.
       
   584         ^ true
       
   585     ].
       
   586     ^ false
       
   587 !
       
   588 
       
   589 cTypeFor:aType
       
   590     "return c-type for an ST-type"
       
   591 
       
   592     (aType == #SmallInteger) ifTrue:[
       
   593         ^ 'int'
       
   594     ].
       
   595     (aType == #Boolean) ifTrue:[
       
   596         ^ 'int'
       
   597     ].
       
   598     (aType == #Float) ifTrue:[
       
   599         ^ 'double'
       
   600     ].
       
   601     (aType == #Character) ifTrue:[
       
   602         ^ 'char'
       
   603     ].
       
   604     (aType == #String) ifTrue:[
       
   605         ^ 'char *'
       
   606     ].
       
   607     (aType == #Symbol) ifTrue:[
       
   608         ^ 'char *'
       
   609     ].
       
   610     (aType == #ByteArray) ifTrue:[
       
   611         ^ 'unsigned char *'
       
   612     ].
       
   613     (aType == nil) ifTrue:[
       
   614         ^ 'void'
       
   615     ].
       
   616     (aType == #ExternalStream) ifTrue:[
       
   617         ^ 'void *'        "actually its FILE *, but better avoid including stdio.h"
       
   618     ].
       
   619     self error:'type ' , aType, ' not supported'.
       
   620     ^ ''
       
   621 ! !
       
   622 
       
   623 !ObjectFileLoader class methodsFor:'loading objects'!
   238 !ObjectFileLoader class methodsFor:'loading objects'!
   624 
   239 
   625 loadFile:oFile with:librariesString
   240 loadFile:oFile with:librariesString
   626     "load in an object files code, linking in libraries"
   241     "load in an object files code, linking in libraries.
   627 
   242      This is only needed if no dynamic link facility exists."
   628     |tmpOfile errStream errors errText ok pid|
   243 
       
   244     |tmpOfile errStream errors errText handle pid cmd|
   629 
   245 
   630     pid := OperatingSystem getProcessId printString.
   246     pid := OperatingSystem getProcessId printString.
   631     tmpOfile := '/tmp/stc_ld' ,  pid.
   247     tmpOfile := '/tmp/stc_ld' ,  pid.
       
   248     cmd := 'ld -o ', tmpOfile, ' -r ' , oFile , ' ' , librariesString , '>/tmp/out 2>/tmp/err'.
   632     Verbose ifTrue:[
   249     Verbose ifTrue:[
   633         Transcript showCr:'executing: ' , ('ld -o ',tmpOfile,' -r ' , oFile , ' ' , librariesString , '>/tmp/out 2>/tmp/err')
   250         ('executing: ld -o ', cmd) errorPrintNL
   634     ].
   251     ].
   635     (OperatingSystem executeCommand:'ld -o ',tmpOfile,' -r ' , oFile , ' ' , librariesString , '>/tmp/out 2>/tmp/err')
   252     (OperatingSystem executeCommand:cmd) ifFalse:[
   636     ifFalse:[
       
   637         errStream := FileStream oldFileNamed:'/tmp/err'.
   253         errStream := FileStream oldFileNamed:'/tmp/err'.
   638         errStream isNil ifTrue:[
   254         errStream isNil ifTrue:[
   639             self notify:'errors during link.'
   255             self notify:'errors during link.'
   640         ] ifFalse:[
   256         ] ifFalse:[
   641             errors := errStream contents.
   257             errors := errStream contents.
   648             OperatingSystem executeCommand:'rm /tmp/err /tmp/out'.
   264             OperatingSystem executeCommand:'rm /tmp/err /tmp/out'.
   649             self notify:('link errors:\\' , errors asString) withCRs
   265             self notify:('link errors:\\' , errors asString) withCRs
   650         ].
   266         ].
   651         ^ false
   267         ^ false
   652     ].
   268     ].
   653     ok := self loadFile:tmpOfile.
   269     handle := self loadFile:tmpOfile.
   654     OperatingSystem executeCommand:('rm ' , tmpOfile).
   270     OperatingSystem executeCommand:('rm ' , tmpOfile).
   655     ^ ok
   271     ^ handle
   656 !
   272 !
   657 
   273 
   658 loadFile:oFile
   274 loadFile:oFile
   659     "load in an object file"
   275     "load in an object file - return a handle or nil.
   660 
   276      This is only needed if no dynamic link facility exists."
   661     | unixCommand errStream errors errText
   277 
   662       text data textSize dataSize dataAddr textAddr newTextSize newDataSize|
   278     |unixCommand errStream errors errText
       
   279      text data textSize dataSize dataAddr textAddr newTextSize newDataSize|
   663 
   280 
   664     "find out, how much memory we need"
   281     "find out, how much memory we need"
   665 
   282 
   666     textSize := ObjectFile textSizeOf:oFile.
   283     textSize := self textSizeOf:oFile.
   667     textSize isNil ifTrue:[
   284     textSize isNil ifTrue:[
   668         Transcript showCr:'bad text-size in object file'.
   285         'bad text-size in object file' errorPrintNL.
   669         ^ false
   286         ^ nil
   670     ].
   287     ].
   671     Verbose ifTrue:[
   288     Verbose ifTrue:[
   672         Transcript showCr:'text-size: ' , (textSize printStringRadix:16)
   289         ('text-size: ' , (textSize printStringRadix:16)) errorPrintNL
   673     ].
   290     ].
   674 
   291 
   675     dataSize := ObjectFile dataSizeOf:oFile.
   292     dataSize := self dataSizeOf:oFile.
   676     dataSize isNil ifTrue:[
   293     dataSize isNil ifTrue:[
   677         Transcript showCr:'bad data-size in object file'.
   294         'bad data-size in object file' errorPrintNL.
   678         ^ false
   295         ^ nil
   679     ].
   296     ].
   680 
   297 
   681     Verbose ifTrue:[
   298     Verbose ifTrue:[
   682         Transcript showCr:'data-size: ' , (dataSize printStringRadix:16)
   299         ('data-size: ' , (dataSize printStringRadix:16)) errorPrintNL
   683     ].
   300     ].
   684 
   301 
   685     "allocate some memory for text and some for data;
   302     "allocate some memory for text and some for data;
   686      then call linker to link the file to those addresses"
   303      then call linker to link the file to those addresses"
   687 
   304 
   688     self needSeparateIDSpaces ifTrue:[
   305     self needSeparateIDSpaces ifTrue:[
   689         text := ExternalBytes newForText:textSize.
   306         text := ExternalBytes newForText:textSize.
   690         text isNil ifTrue:[
   307         text isNil ifTrue:[
   691             Transcript showCr:'cannot allocate memory for text'.
   308             'cannot allocate memory for text' errorPrintNL.
   692             ^ false
   309             ^ nil
   693         ].
   310         ].
   694 
   311 
   695         Verbose ifTrue:[
   312         Verbose ifTrue:[
   696             Transcript showCr:'text: ' , (text address printStringRadix:16)
   313             ('text: ' , (text address printStringRadix:16)) errorPrintNL
   697         ].
   314         ].
   698 
   315 
   699         (dataSize ~~ 0) ifTrue:[
   316         (dataSize ~~ 0) ifTrue:[
   700             data := ExternalBytes newForData:dataSize.
   317             data := ExternalBytes newForData:dataSize.
   701             (data isNil) ifTrue:[
   318             (data isNil) ifTrue:[
   702                 Transcript showCr:'cannot allocate memory for data'.
   319                 'cannot allocate memory for data' errorPrintNL.
   703                 text notNil ifTrue:[text free].
   320                 text notNil ifTrue:[text free].
   704                 ^ false
   321                 ^ nil
   705             ].
   322             ].
   706             Verbose ifTrue:[
   323             Verbose ifTrue:[
   707                 Transcript showCr:'data: ' , (data address printStringRadix:16)
   324                 ('data: ' , (data address printStringRadix:16)) errorPrintNL
   708             ]
   325             ]
   709         ].
   326         ].
   710         dataSize == 0 ifTrue:[
   327         dataSize == 0 ifTrue:[
   711             unixCommand := (self absLd:oFile text:text address) 
   328             unixCommand := (self absLd:oFile text:text address) , ' >/tmp/out 2>/tmp/err'.
   712                            , ' >/tmp/out 2>/tmp/err'.
       
   713         ] ifFalse:[
   329         ] ifFalse:[
   714             unixCommand := (self absLd:oFile text:text address 
   330             unixCommand := (self absLd:oFile text:text address data:data address) 
   715                                              data:data address) 
       
   716                            , ' >/tmp/out 2>/tmp/err'.
   331                            , ' >/tmp/out 2>/tmp/err'.
   717         ]
   332         ]
   718     ] ifFalse:[
   333     ] ifFalse:[
   719         text := ExternalBytes newForText:(textSize + dataSize).
   334         text := ExternalBytes newForText:(textSize + dataSize).
   720         text isNil ifTrue:[
   335         text isNil ifTrue:[
   721             Transcript showCr:'cannot allocate memory for text+data'.
   336             'cannot allocate memory for text+data' errorPrintNL.
   722             ^ false
   337             ^ nil
   723         ].
   338         ].
   724         Verbose ifTrue:[
   339         Verbose ifTrue:[
   725             Transcript showCr:'addr: ' , (text address printStringRadix:16)
   340             ('addr: ' , (text address printStringRadix:16)) errorPrintNL
   726         ].
   341         ].
   727         unixCommand := (self absLd:oFile text:text address) 
   342         unixCommand := (self absLd:oFile text:text address) , ' >/tmp/out 2>/tmp/err'.
   728                        , ' >/tmp/out 2>/tmp/err'.
       
   729     ].
   343     ].
   730 
   344 
   731     Verbose ifTrue:[
   345     Verbose ifTrue:[
   732         Transcript showCr:'executing: ' , unixCommand
   346         ('executing: ' , unixCommand) errorPrintNL
   733     ].
   347     ].
   734 
   348 
   735     'linking ...' printNewline.
   349     'linking ...' printNewline.
   736     (OperatingSystem executeCommand:unixCommand) ifFalse: [
   350     (OperatingSystem executeCommand:unixCommand) ifFalse: [
   737         errStream := FileStream oldFileNamed:'/tmp/err'.
   351         errStream := FileStream oldFileNamed:'/tmp/err'.
   744                 errors := errText
   358                 errors := errText
   745             ].
   359             ].
   746             OperatingSystem executeCommand:'rm /tmp/err /tmp/out'.
   360             OperatingSystem executeCommand:'rm /tmp/err /tmp/out'.
   747             self notify:('link errors:\\' , errors asString) withCRs
   361             self notify:('link errors:\\' , errors asString) withCRs
   748         ].
   362         ].
   749         Transcript showCr:'link unsuccessful.'.
   363         'link unsuccessful.' errorPrintNL.
   750         text notNil ifTrue:[text free].
   364         text notNil ifTrue:[text free].
   751         data notNil ifTrue:[data free].
   365         data notNil ifTrue:[data free].
   752         ^ false
   366         ^ nil
   753     ].
   367     ].
   754 
   368 
   755     'link successful' printNewline.
   369     'link successful' errorPrintNL.
   756 
   370 
   757     OperatingSystem executeCommand:'rm /tmp/err /tmp/out'.
   371     OperatingSystem executeCommand:'rm /tmp/err /tmp/out'.
   758 
   372 
   759     "find out, if space needs have changed after link (they do so on some machines)"
   373     "find out, if space needs have changed after link (they do so on some machines)"
   760 
   374 
   761     newTextSize := ObjectFile textSizeOf:'a.out'.
   375     newTextSize := self textSizeOf:'a.out'.
   762     newTextSize isNil ifTrue:[
   376     newTextSize isNil ifTrue:[
   763         Transcript showCr:'bad new-text-size in a.out object file'.
   377         'bad new-text-size in a.out object file' errorPrintNL.
   764         text notNil ifTrue:[text free].
   378         text notNil ifTrue:[text free].
   765         data notNil ifTrue:[data free].
   379         data notNil ifTrue:[data free].
   766         ^ false
   380         ^ nil
   767     ].
   381     ].
   768     Verbose ifTrue:[
   382     Verbose ifTrue:[
   769         Transcript showCr:'new-text-size: ' , (newTextSize printStringRadix:16)
   383         ('new-text-size: ' , (newTextSize printStringRadix:16)) errorPrintNL
   770     ].
   384     ].
   771 
   385 
   772     newDataSize := ObjectFile dataSizeOf:'a.out'.
   386     newDataSize := self dataSizeOf:'a.out'.
   773     newDataSize isNil ifTrue:[
   387     newDataSize isNil ifTrue:[
   774         Transcript showCr:'bad new-data-size in a.out object file'.
   388         'bad new-data-size in a.out object file' errorPrintNL.
   775         text notNil ifTrue:[text free].
   389         text notNil ifTrue:[text free].
   776         data notNil ifTrue:[data free].
   390         data notNil ifTrue:[data free].
   777         ^ false
   391         ^ nil
   778     ].
   392     ].
   779 
   393 
   780     Verbose ifTrue:[
   394     Verbose ifTrue:[
   781         Transcript showCr:'new-data-size: ' , (newDataSize printStringRadix:16)
   395         ('new-data-size: ' , (newDataSize printStringRadix:16)) errorPrintNL
   782     ].
   396     ].
   783 
   397 
   784     "if size has changed, do it again"
   398     "if size has changed, do it again"
   785 
   399 
   786     ((newTextSize ~~ textSize) or:[newDataSize ~~ dataSize]) ifTrue:[
   400     ((newTextSize ~~ textSize) or:[newDataSize ~~ dataSize]) ifTrue:[
   793         dataSize := newDataSize.
   407         dataSize := newDataSize.
   794 
   408 
   795         self needSeparateIDSpaces ifTrue:[
   409         self needSeparateIDSpaces ifTrue:[
   796             text := ExternalBytes newForText:textSize.
   410             text := ExternalBytes newForText:textSize.
   797             text isNil ifTrue:[
   411             text isNil ifTrue:[
   798                 Transcript showCr:'cannot allocate memory for text'.
   412                 'cannot allocate memory for new text' errorPrintNL.
   799                 ^ false
   413                 ^ nil
   800             ].
   414             ].
   801 
   415 
   802             Verbose ifTrue:[
   416             Verbose ifTrue:[
   803                 Transcript showCr:'text: ' , (text address printStringRadix:16)
   417                 ('new text: ' , (text address printStringRadix:16)) errorPrintNL
   804             ].
   418             ].
   805 
   419 
   806             (dataSize ~~ 0) ifTrue:[
   420             (dataSize ~~ 0) ifTrue:[
   807                 data := ExternalBytes newForData:dataSize.
   421                 data := ExternalBytes newForData:dataSize.
   808                 (data isNil) ifTrue:[
   422                 (data isNil) ifTrue:[
   809                     Transcript showCr:'cannot allocate memory for data'.
   423                     'cannot allocate memory for new data' errorPrintNL.
   810                     text notNil ifTrue:[text free].
   424                     text notNil ifTrue:[text free].
   811                     ^ false
   425                     ^ nil
   812                 ].
   426                 ].
   813                 Verbose ifTrue:[
   427                 Verbose ifTrue:[
   814                     Transcript showCr:'data: ' , (data address printStringRadix:16)
   428                     ('new data: ' , (data address printStringRadix:16)) errorPrintNL
   815                 ]
   429                 ]
   816             ].
   430             ].
   817 
   431 
   818             dataSize == 0 ifTrue:[
   432             dataSize == 0 ifTrue:[
   819                 unixCommand := (self absLd:oFile text:text address) 
   433                 unixCommand := (self absLd:oFile text:text address) , ' >/tmp/out 2>/tmp/err'.
   820                                , ' >/tmp/out 2>/tmp/err'.
       
   821             ] ifFalse:[
   434             ] ifFalse:[
   822                 unixCommand := (self absLd:oFile text:text address 
   435                 unixCommand := (self absLd:oFile text:text address data:data address) 
   823                                                  data:data address) 
       
   824                                , ' >/tmp/out 2>/tmp/err'.
   436                                , ' >/tmp/out 2>/tmp/err'.
   825             ]
   437             ]
   826         ] ifFalse:[
   438         ] ifFalse:[
   827             text := ExternalBytes newForText:(textSize + dataSize).
   439             text := ExternalBytes newForText:(textSize + dataSize).
   828             text isNil ifTrue:[
   440             text isNil ifTrue:[
   829                 Transcript showCr:'cannot allocate memory for text'.
   441                 'cannot allocate memory for new text' errorPrintNL.
   830                 ^ false
   442                 ^ nil
   831             ].
   443             ].
   832             Verbose ifTrue:[
   444             Verbose ifTrue:[
   833                 Transcript showCr:'addr: ' , (text address printStringRadix:16)
   445                 ('new text+data: ' , (text address printStringRadix:16)) errorPrintNL
   834             ].
   446             ].
   835             unixCommand := (self absLd:oFile text:text address) 
   447             unixCommand := (self absLd:oFile text:text address) , ' >/tmp/out 2>/tmp/err'.
   836                            , ' >/tmp/out 2>/tmp/err'.
       
   837         ].
   448         ].
   838 
   449 
   839         Verbose ifTrue:[
   450         Verbose ifTrue:[
   840             Transcript showCr:'executing: ' , unixCommand
   451             ('executing: ' , unixCommand) errorPrintNL
   841         ].
   452         ].
   842 
   453 
   843         'linking ...' printNewline.
   454         'linking ...' errorPrintNL.
   844         (OperatingSystem executeCommand:unixCommand) ifFalse: [
   455         (OperatingSystem executeCommand:unixCommand) ifFalse: [
   845             errStream := FileStream oldFileNamed:'/tmp/err'.
   456             errStream := FileStream oldFileNamed:'/tmp/err'.
   846             errStream notNil ifTrue:[
   457             errStream notNil ifTrue:[
   847                 errors := errStream contents.
   458                 errors := errStream contents.
   848                 errText := errors asText.
   459                 errText := errors asText.
   852                     errors := errText
   463                     errors := errText
   853                 ].
   464                 ].
   854                 OperatingSystem executeCommand:'rm /tmp/err /tmp/out'.
   465                 OperatingSystem executeCommand:'rm /tmp/err /tmp/out'.
   855                 self notify:('link errors:\\' , errors asString) withCRs
   466                 self notify:('link errors:\\' , errors asString) withCRs
   856             ].
   467             ].
   857             Transcript showCr:'link unsuccessful.'.
   468             'link unsuccessful.' errorPrintNL.
   858             text notNil ifTrue:[text free].
   469             text notNil ifTrue:[text free].
   859             data notNil ifTrue:[data free].
   470             data notNil ifTrue:[data free].
   860             ^ false
   471             ^ nil
   861         ].
   472         ].
   862 
   473 
   863         'link successful' printNewline.
   474         'link successful' errorPrintNL.
   864 
   475 
   865         OperatingSystem executeCommand:'rm /tmp/err /tmp/out'.
   476         OperatingSystem executeCommand:'rm /tmp/err /tmp/out'.
   866 
   477 
   867         "check again for size change - should not happen"
   478         "check again for size change - should not happen"
   868 
   479 
   869         newTextSize := ObjectFile textSizeOf:'a.out'.
   480         newTextSize := self textSizeOf:'a.out'.
   870         newTextSize isNil ifTrue:[
   481         newTextSize isNil ifTrue:[
   871             Transcript showCr:'bad text-size in a.out object file'.
   482             'bad text-size in a.out object file' errorPrintNL.
   872             text notNil ifTrue:[text free].
   483             text notNil ifTrue:[text free].
   873             data notNil ifTrue:[data free].
   484             data notNil ifTrue:[data free].
   874             ^ false
   485             ^ nil
   875         ].
   486         ].
   876         Verbose ifTrue:[
   487         Verbose ifTrue:[
   877             Transcript showCr:'new-text-size: ' , (newTextSize printStringRadix:16)
   488             ('new-text-size: ' , (newTextSize printStringRadix:16)) errorPrintNL
   878         ].
   489         ].
   879 
   490 
   880         newDataSize := ObjectFile dataSizeOf:'a.out'.
   491         newDataSize := self dataSizeOf:'a.out'.
   881         newDataSize isNil ifTrue:[
   492         newDataSize isNil ifTrue:[
   882             Transcript showCr:'bad data-size in object file'.
   493             'bad data-size in object file' errorPrintNL.
   883             text notNil ifTrue:[text free].
   494             text notNil ifTrue:[text free].
   884             data notNil ifTrue:[data free].
   495             data notNil ifTrue:[data free].
   885             ^ false
   496             ^ nil
   886         ].
   497         ].
   887 
   498 
   888         Verbose ifTrue:[
   499         Verbose ifTrue:[
   889             Transcript showCr:'new-data-size: ' , (newDataSize printStringRadix:16)
   500             ('new-data-size: ' , (newDataSize printStringRadix:16)) errorPrintNL
   890         ].
   501         ].
   891 
   502 
   892         ((newTextSize ~~ textSize) or:[newDataSize ~~ dataSize]) ifTrue:[
   503         ((newTextSize ~~ textSize) or:[newDataSize ~~ dataSize]) ifTrue:[
   893             Transcript showCr:'size changed again - I give up'.
   504             'size changed again - I give up' errorPrintNL.
   894             text notNil ifTrue:[text free].
   505             text notNil ifTrue:[text free].
   895             data notNil ifTrue:[data free].
   506             data notNil ifTrue:[data free].
   896             ^ false
   507             ^ nil
   897         ].
   508         ].
   898     ].
   509     ].
   899 
   510 
   900     "only thing left to do is to load in text at textAddr and
   511     "only thing left to do is to load in text at textAddr and
   901      data at dataAddr ... "
   512      data at dataAddr ... "
   911         dataAddr := nil
   522         dataAddr := nil
   912     ].
   523     ].
   913 
   524 
   914     Verbose ifTrue:[
   525     Verbose ifTrue:[
   915         textAddr notNil ifTrue:[
   526         textAddr notNil ifTrue:[
   916             Transcript showCr:'loading ' , textSize printString , ' bytes at ' , (textAddr printStringRadix:16).
   527             ('loading ' , textSize printString , ' bytes at ' , (textAddr printStringRadix:16)) errorPrintNL.
   917         ].
   528         ].
   918         dataAddr notNil ifTrue:[
   529         dataAddr notNil ifTrue:[
   919             Transcript showCr:'loading ' , dataSize printString , ' bytes at ' , (dataAddr printStringRadix:16).
   530             ('loading ' , dataSize printString , ' bytes at ' , (dataAddr printStringRadix:16)) errorPrintNL.
   920         ].
   531         ].
   921     ].
   532     ].
   922 
   533 
   923     (ObjectFile loadObjectFile:'a.out'
   534     (self loadObjectFile:'a.out'
   924                 textAddr:textAddr textSize:textSize
   535                 textAddr:textAddr textSize:textSize
   925                 dataAddr:dataAddr dataSize:dataSize) isNil ifTrue: [
   536                 dataAddr:dataAddr dataSize:dataSize) isNil ifTrue: [
   926         Transcript showCr:'load in error'.
   537         'load error' errorPrintNL.
   927         text notNil ifTrue:[text free].
   538         text notNil ifTrue:[text free].
   928         data notNil ifTrue:[data free].
   539         data notNil ifTrue:[data free].
   929         ^ false
   540         ^ nil
   930     ].
   541     ].
   931 
   542 
   932     'dynamic load successful' printNewline.
   543     'dynamic load successful' errorPrintNL.
   933 
   544 
   934     OperatingSystem executeCommand:'mv a.out SymbolTable'.
   545     OperatingSystem executeCommand:'mv a.out SymbolTable'.
   935     MySymbolTable := 'SymbolTable'.
   546     MySymbolTable := 'SymbolTable'.
   936     ^ true
   547     ^ (Array with:textAddr with:dataAddr)
   937 ! !
   548 ! !
   938 
   549 
   939 !ObjectFileLoader class methodsFor:'dynamic class loading'!
   550 !ObjectFileLoader class methodsFor:'dynamic class loading'!
   940 
   551 
   941 loadClass:aClassName fromObjectFile:aFileName
   552 loadClass:aClassName fromObjectFile:aFileName
   942     "load a compiled class (.o-file) into the image"
   553     "load a compiled class (.o-file) into the image"
   943 
   554 
   944     |handle initAddr symName|
   555     |handle initAddr symName newClass list moreHandles|
   945 
   556 
   946     handle := self openDynamicObject:aFileName.
   557     handle := self openDynamicObject:aFileName.
   947     handle isNil ifTrue:[
   558     handle isNil ifTrue:[
   948         Transcript showCr:('openDynamic: ',aFileName,' failed.').
   559         Transcript showCr:('openDynamic: ',aFileName,' failed.').
   949         ^ nil
   560         ^ nil
   950     ].
   561     ].
       
   562 
       
   563     "
       
   564      get the Init-function; let the class install itself
       
   565     "
   951     symName := '_' , aClassName , '_Init'.
   566     symName := '_' , aClassName , '_Init'.
   952     initAddr := self getSymbol:symName from:handle.
   567     initAddr := self getFunction:symName from:handle.
   953     initAddr isNil ifTrue:[
   568     initAddr isNil ifTrue:[
   954         "try with added underscore"
   569         "try with added underscore"
   955         symName := '__' , aClassName , '_Init'.
   570         symName := '__' , aClassName , '_Init'.
   956         initAddr := self getSymbol:symName from:handle.
   571         initAddr := self getFunction:symName from:handle.
       
   572     ].
       
   573 
       
   574     "
       
   575      if there are any undefined symbols, we may have to load more
       
   576     "
       
   577     list := self getListOfUndefinedSymbolsFrom:handle.
       
   578     list notNil ifTrue:[
       
   579         moreHandles := self loadModulesFromListOfUndefined:list.
       
   580 
       
   581         "
       
   582          now, try again
       
   583         "
       
   584         symName := '_' , aClassName , '_Init'.
       
   585         initAddr := self getFunction:symName from:handle.
   957         initAddr isNil ifTrue:[
   586         initAddr isNil ifTrue:[
   958             Transcript showCr:('no symbol: ',symName,' in ',aFileName).
   587             "try with added underscore"
   959             ^ nil
   588             symName := '__' , aClassName , '_Init'.
   960         ].
   589             initAddr := self getFunction:symName from:handle.
   961     ].
   590         ].
   962     self callFunctionAt:initAddr.
   591     ].
   963     ^ Smalltalk at:aClassName asSymbol
   592 
       
   593     initAddr notNil ifTrue:[
       
   594         Verbose ifTrue:[
       
   595             Transcript showCr:'calling init at: ' , (initAddr printStringRadix:16)
       
   596         ].
       
   597         self callInitFunctionAt:initAddr.
       
   598         (Symbol hasInterned:aClassName) ifTrue:[
       
   599             newClass := Smalltalk at:aClassName asSymbol ifAbsent:[nil].
       
   600             newClass notNil ifTrue:[
       
   601                 newClass initialize.
       
   602                 "force cache flush"
       
   603                 Smalltalk at:aClassName asSymbol put:newClass.
       
   604                 Smalltalk changed.
       
   605             ].
       
   606         ] ifFalse:[
       
   607             'LOADER: class ' errorPrintNL. aClassName errorPrintNL.
       
   608             ' did not define itself' errorPrintNL
       
   609             "
       
   610              do not unload - could have installed its methods ...
       
   611             "
       
   612         ].
       
   613         ^ newClass
       
   614     ].
       
   615 
       
   616     Verbose ifTrue:[
       
   617         Transcript showCr:('no symbol: ', symName,' in ',aFileName).
       
   618     ].
       
   619 
       
   620     "
       
   621      unload
       
   622     "
       
   623     moreHandles notNil ifTrue:[
       
   624         self closeAllDynamicObjects:moreHandles.
       
   625     ].
       
   626     self closeDynamicObject:handle.
       
   627     ^ nil
   964 
   628 
   965     "ObjectFileLoader loadClass:'Tetris'      fromObjectFile:'../clients/Tetris/Tetris.o'"
   629     "ObjectFileLoader loadClass:'Tetris'      fromObjectFile:'../clients/Tetris/Tetris.o'"
   966     "ObjectFileLoader loadClass:'TetrisBlock' fromObjectFile:'../clients/Tetris/TBlock.o'"
   630     "ObjectFileLoader loadClass:'TetrisBlock' fromObjectFile:'../clients/Tetris/TBlock.o'"
       
   631     "ObjectFileLoader loadClass:'Foo'         fromObjectFile:'classList.o'"
   967 !
   632 !
   968 
   633 
   969 loadObjectFile:aFileName
   634 loadObjectFile:aFileName
   970     "load a compiled class (.o-file) into the image; the class name
   635     "load an object file (.o-file) into the image; 
   971      is not needed (multiple definitions may be in the file)"
   636      the class name is not needed (multiple definitions may be in the file)."
   972 
   637 
   973     |handle initAddr symName className|
   638     |handle initAddr symName className newClass list|
   974 
   639 
   975     handle := self openDynamicObject:aFileName.
   640     handle := self openDynamicObject:aFileName.
   976     handle isNil ifTrue:[
   641     handle isNil ifTrue:[
   977         Transcript showCr:('openDynamic: ',aFileName,' failed.').
   642         Transcript showCr:('openDynamic: ',aFileName,' failed.').
   978         ^ nil
   643         ^ nil
   979     ].
   644     ].
   980 
   645 
   981     "load worked - now get init functions address"
   646     "
   982 
   647      look for init-function
       
   648     "
   983     className := OperatingSystem baseNameOf:aFileName.
   649     className := OperatingSystem baseNameOf:aFileName.
   984     (className endsWith:'.o') ifTrue:[
   650     (className endsWith:'.o') ifTrue:[
   985         className := className copyTo:(className size - 2)
   651         className := className copyTo:(className size - 2)
   986     ].
   652     ].
   987     symName := '_' , className , '_Init'.
   653     symName := '_' , className , '_Init'.
   988     initAddr := self getSymbol:symName from:handle.
   654     initAddr := self getFunction:symName from:handle.
   989 
   655 
   990     initAddr isNil ifTrue:[
   656     initAddr isNil ifTrue:[
   991         "try with added underscore"
   657         "try with added underscore"
   992         symName := '__' , className , '_Init'.
   658         symName := '__' , className , '_Init'.
   993         initAddr := self getSymbol:symName from:handle.
   659         initAddr := self getFunction:symName from:handle.
   994         initAddr isNil ifTrue:[
   660         initAddr isNil ifTrue:[
   995             "try className from fileName"
   661             "try className from fileName"
   996             className := Smalltalk classNameForFile:className.
   662             className := Smalltalk classNameForFile:className.
   997             symName := '_' , className , '_Init'.
   663             symName := '_' , className , '_Init'.
   998             initAddr := self getSymbol:symName from:handle.
   664             initAddr := self getFunction:symName from:handle.
   999             initAddr isNil ifTrue:[
   665             initAddr isNil ifTrue:[
  1000                 "and with added underscore"
   666                 "and with added underscore"
  1001                 symName := '__' , className , '_Init'.
   667                 symName := '__' , className , '_Init'.
  1002                 initAddr := self getSymbol:symName from:handle.
   668                 initAddr := self getFunction:symName from:handle.
  1003                 initAddr isNil ifTrue:[
   669                 initAddr isNil ifTrue:[
  1004                     Transcript showCr:('no symbol: ',symName,' in ',aFileName).
   670                     Transcript showCr:('no symbol: ',symName,' in ',aFileName).
       
   671                     "
       
   672                      unload
       
   673                     "
       
   674                     self closeDynamicObject:handle.
  1005                     ^ nil
   675                     ^ nil
  1006                 ].
   676                 ].
  1007             ].
   677             ].
  1008         ].
   678         ].
  1009     ].
   679     ].
  1010     self callFunctionAt:initAddr.
   680     Verbose ifTrue:[
       
   681         Transcript showCr:'calling init at:' , (initAddr printStringRadix:16)
       
   682     ].
       
   683     self callInitFunctionAt:initAddr.
       
   684 
       
   685     (Symbol hasInterned:className) ifTrue:[
       
   686         newClass := Smalltalk at:className asSymbol ifAbsent:[nil].
       
   687         newClass notNil ifTrue:[
       
   688             newClass initialize.
       
   689             "force cache flush"
       
   690             Smalltalk at:className asSymbol put:newClass.
       
   691             Smalltalk changed.
       
   692         ].
       
   693     ].
       
   694     ^ newClass
       
   695 !
       
   696 
       
   697 loadCPlusPlusObjectFile:aFileName
       
   698     "load a c++ object file (.o-file) into the image"
       
   699 
       
   700     |handle initAddr symName className newClass list|
       
   701 
       
   702     handle := self openDynamicObject:aFileName.
       
   703     handle isNil ifTrue:[
       
   704         Transcript showCr:('openDynamic: ',aFileName,' failed.').
       
   705         ^ nil
       
   706     ].
       
   707 
       
   708     list := self namesMatching:'__GLOBAL_$I*' in:aFileName.
       
   709 list size == 1 ifTrue:[
       
   710 "/    (self isCPlusPlusObject:handle) ifTrue:[
       
   711         Verbose ifTrue:[
       
   712             Transcript showCr:'a c++ object file'
       
   713         ].
       
   714         "
       
   715          what I would like to get is the CTOR_LIST,
       
   716          and call each function.
       
   717          But dld cannot (currently) handle SET-type symbols, therefore
       
   718          we search (using nm) for all __GLOBAL_$I* syms, get their values
       
   719          and call them each
       
   720         "
       
   721 "/        list := self namesMatching:'__GLOBAL_$I*' in:aFileName.
       
   722 
       
   723 "/        initAddr := self getFunction:'__CTOR_LIST__' from:handle.
       
   724 "/        Verbose ifTrue:[
       
   725 "/            Transcript showCr:'calling CTORs at:' , (initAddr printStringRadix:16)
       
   726 "/        ].
       
   727 
       
   728         initAddr := self getFunction:list first from:handle.
       
   729         initAddr isNil ifTrue:[
       
   730             "
       
   731              try with added underscore
       
   732             "
       
   733             initAddr := self getFunction:('_' , list first) from:handle.
       
   734         ].
       
   735         (initAddr isNil and:[list first startsWith:'_']) ifTrue:[
       
   736             "
       
   737              try with removed underscore
       
   738             "
       
   739             initAddr := self getFunction:(list first copyFrom:2) from:handle.
       
   740         ].
       
   741         initAddr isNil ifTrue:[
       
   742             Verbose ifTrue:[
       
   743                 Transcript showCr:'no CTOR-func found (' , list first , ')'
       
   744             ].
       
   745             self closeDynamicObject:aFileName.
       
   746             ^ nil
       
   747         ].
       
   748         Verbose ifTrue:[
       
   749             Transcript showCr:'calling CTORs at:' , (initAddr printStringRadix:16)
       
   750         ].
       
   751         self callFunctionAt:initAddr forceOld:false arg:0.
       
   752         Verbose ifTrue:[
       
   753             Transcript showCr:'done with CTORs.'
       
   754         ].
       
   755 
       
   756         "
       
   757          cannot create a CPlusPlus class automatically (there could be more than
       
   758          one classes in it too ...)
       
   759         "
       
   760         ^ handle
       
   761     ].
       
   762 
       
   763 
       
   764     Verbose ifTrue:[
       
   765         Transcript showCr:'unknown object file'
       
   766     ].
       
   767     self closeDynamicObject:aFileName.
       
   768     ^ nil
       
   769 !
       
   770 
       
   771 loadModulesFromListOfUndefined:list
       
   772     "try to figure out what has to be loaded to resolve symbols from list.
       
   773      return a list of handles of loaded objects
       
   774     "
       
   775     |inits classNames moreHandles|
       
   776 
       
   777     inits := list select:[:symbol | symbol notNil and:[symbol endsWith:'_Init']].
       
   778     inits notNil ifTrue:[
       
   779         classNames := inits collect:[:symbol |
       
   780             (symbol startsWith:'___') ifTrue:[
       
   781                 symbol copyFrom:4 to:(symbol size - 5)
       
   782             ] ifFalse:[
       
   783                 (symbol startsWith:'__') ifTrue:[
       
   784                     symbol copyFrom:3 to:(symbol size - 5)
       
   785                 ] ifFalse:[
       
   786                     (symbol startsWith:'_') ifTrue:[
       
   787                         symbol copyFrom:2 to:(symbol size - 5)
       
   788                     ] ifFalse:[
       
   789                         symbol
       
   790                     ]
       
   791                 ]
       
   792             ]
       
   793         ].
       
   794         "
       
   795          autoload those classes
       
   796         "
       
   797         classNames do:[:aClassName |
       
   798             aClassName knownAsSymbol ifTrue:[
       
   799                 (Smalltalk includesKey:aClassName asSymbol) ifTrue:[
       
   800 'autoloading ' print. aClassName printNL.
       
   801                     (Smalltalk at:aClassName asSymbol) autoload
       
   802                 ]
       
   803             ]
       
   804         ]
       
   805     ].
       
   806     ^ nil
  1011 ! !
   807 ! !
  1012 
   808 
  1013 !ObjectFileLoader class methodsFor:'dynamic object access'!
   809 !ObjectFileLoader class methodsFor:'dynamic object access'!
  1014 
   810 
  1015 openDynamicObject:pathName
   811 openDynamicObject:pathName
  1016     "open an object-file (map into my address space).
   812     "open an object-file (load/map into my address space).
  1017      Return a non-nil handle if ok, nil otherwise.
   813      Return a non-nil handle if ok, nil otherwise.
  1018      This function is not supported on all architectures."
   814      No bindings are done - only a pure load is performed.
       
   815      This function is not supported on all architectures.
       
   816     "
  1019 
   817 
  1020     |handle|
   818     |handle|
  1021 
   819 
       
   820     Verbose ifTrue:[
       
   821         Transcript showCr:'openDynamic: ' , pathName
       
   822     ].
       
   823 
  1022     handle := self primOpenDynamicObject:pathName into:(Array new:2).
   824     handle := self primOpenDynamicObject:pathName into:(Array new:2).
       
   825     handle isNil ifTrue:[
       
   826         Verbose ifTrue:[
       
   827             Transcript showCr:'no dynamic load facility or load failed.'.
       
   828         ].
       
   829         "try it the hard way"
       
   830         handle := self loadFile:pathName.
       
   831     ].
  1023     ^ handle
   832     ^ handle
  1024 
   833 
  1025     "sys5.4:
   834     "sys5.4:
  1026      |handle|
   835      |handle|
  1027      handle := ObjectFileLoader openDynamicObject:'../stc/mod1.so'.
   836      handle := ObjectFileLoader openDynamicObject:'../stc/mod1.so'.
  1028      ObjectFileLoader getSymbol:'module1' from:handle
   837      ObjectFileLoader getFunction:'module1' from:handle
  1029     "
   838     "
  1030     "next:
   839     "next:
  1031      |handle|
   840      |handle|
  1032      handle := ObjectFileLoader openDynamicObject:'../goodies/Path/AbstrPath.o'.
   841      handle := ObjectFileLoader openDynamicObject:'../goodies/Path/AbstrPath.o'.
  1033      ObjectFileLoader getSymbol:'__AbstractPath_Init' from:handle
   842      ObjectFileLoader getFunction:'__AbstractPath_Init' from:handle
  1034     "
   843     "
  1035     "GLD:
   844     "GLD:
  1036      |handle|
   845      |handle|
  1037      handle := ObjectFileLoader openDynamicObject:'../clients/Tetris/Tetris.o'.
   846      handle := ObjectFileLoader openDynamicObject:'../clients/Tetris/Tetris.o'.
  1038      ObjectFileLoader getSymbol:'__TetrisBlock_Init' from:handle
   847      ObjectFileLoader getFunction:'__TetrisBlock_Init' from:handle
  1039     "
   848     "
  1040 !
   849 !
  1041 
   850 
  1042 primOpenDynamicObject:pathName into:aBuffer
   851 primOpenDynamicObject:pathName into:aBuffer
  1043     "open an object-file (map into my address space).
   852     "open an object-file (map into my address space).
  1044      This function is not supported on all architectures.
   853      This function is not supported on all architectures.
  1045      Dont depend on the returned value or class of it, it depends
   854      Dont depend on the values or types returned in aBuffer, 
  1046      on the underlying dynamic load package."
   855      it depends on the underlying dynamic load package."
  1047 
   856 
  1048 %{  /* UNLIMITEDSTACK */
   857 %{  /* UNLIMITEDSTACK */
  1049 
   858 
  1050 #ifdef GNU_DL
   859 #ifdef GNU_DL
  1051 #   include "dld.h"
   860 #   include "dld.h"
       
   861     static firstCall = 1;
       
   862     extern char *__myName__;
       
   863 
       
   864     if (firstCall) {
       
   865         firstCall = 0;
       
   866         (void) dld_init (__myName__);
       
   867     }
       
   868 
  1052     if (__isString(pathName)) {
   869     if (__isString(pathName)) {
  1053         if (dld_link(_stringVal(pathName))) {
   870         if (dld_link(_stringVal(pathName))) {
  1054             dld_perror("cant link");
   871             dld_perror("cant link");
  1055             RETURN ( nil );
   872             RETURN ( nil );
  1056         }
   873         }
  1068             handle = dlopen((char *)0, RTLD_NOW);
   885             handle = dlopen((char *)0, RTLD_NOW);
  1069         else
   886         else
  1070             handle = dlopen(_stringVal(pathName), RTLD_NOW);
   887             handle = dlopen(_stringVal(pathName), RTLD_NOW);
  1071 
   888 
  1072         if (! handle) {
   889         if (! handle) {
  1073             printf("dlopen %s error: <%s>\n", _stringVal(pathName), dlerror());
   890             fprintf(stderr, "dlopen %s error: <%s>\n", _stringVal(pathName), dlerror());
  1074             RETURN (nil);
   891             RETURN (nil);
  1075         }
   892         }
  1076 
   893 
  1077         printf("open %s handle = %x\n", _stringVal(pathName), handle);
   894         if (ObjectFileLoader_Verbose == true)
       
   895             printf("open %s handle = %x\n", _stringVal(pathName), handle);
  1078         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(1), 
   896         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(1), 
  1079                                    _MKSMALLINT( (int)handle & 0xFFFF ));
   897                                    _MKSMALLINT( (int)handle & 0xFFFF ));
  1080         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(2), 
   898         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(2), 
  1081                                    _MKSMALLINT( ((int)handle >> 16) & 0xFFFF ));
   899                                    _MKSMALLINT( ((int)handle >> 16) & 0xFFFF ));
  1082     }
   900     }
  1084 
   902 
  1085 #ifdef SUN_DL
   903 #ifdef SUN_DL
  1086 #   include <dlfcn.h>
   904 #   include <dlfcn.h>
  1087     void *handle;
   905     void *handle;
  1088 
   906 
  1089     loadAddrLow = nil;
       
  1090     loadAddrHi = nil;
       
  1091     if ((pathName == nil) || __isString(pathName)) {
   907     if ((pathName == nil) || __isString(pathName)) {
  1092         if (pathName == nil)
   908         if (pathName == nil)
  1093             handle = dlopen((char *)0, 1);
   909             handle = dlopen((char *)0, 1);
  1094         else
   910         else
  1095             handle = dlopen(_stringVal(pathName), 1);
   911             handle = dlopen(_stringVal(pathName), 1);
  1096 
   912 
  1097         if (! handle) {
   913         if (! handle) {
  1098             printf("dlopen %s error: <%s>\n", _stringVal(pathName), dlerror());
   914             fprintf(stderr, "dlopen %s error: <%s>\n", _stringVal(pathName), dlerror());
  1099             RETURN (nil);
   915             RETURN (nil);
  1100         }
   916         }
  1101 
   917 
  1102         printf("open %s handle = %x\n", _stringVal(pathName), handle);
   918         if (ObjectFileLoader_Verbose == true)
       
   919             printf("open %s handle = %x\n", _stringVal(pathName), handle);
  1103         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(1), 
   920         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(1), 
  1104                                    _MKSMALLINT( (int)handle & 0xFFFF ));
   921                                    _MKSMALLINT( (int)handle & 0xFFFF ));
  1105         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(2), 
   922         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(2), 
  1106                                    _MKSMALLINT( ((int)handle >> 16) & 0xFFFF ));
   923                                    _MKSMALLINT( ((int)handle >> 16) & 0xFFFF ));
  1107     }
   924     }
  1110 #ifdef NEXT_DL
   927 #ifdef NEXT_DL
  1111     long result;
   928     long result;
  1112     char *files[2];
   929     char *files[2];
  1113     NXStream *errOut;
   930     NXStream *errOut;
  1114 
   931 
  1115     loadAddrLow = nil;
       
  1116     loadAddrHi = nil;
       
  1117     if (__isString(pathName)) {
   932     if (__isString(pathName)) {
  1118         files[0] = (char *) _stringVal(pathName);
   933         files[0] = (char *) _stringVal(pathName);
  1119         files[1] = (char *) 0;
   934         files[1] = (char *) 0;
  1120         errOut = NXOpenFile(2, 2);
   935         errOut = NXOpenFile(2, 2);
  1121         result = rld_load(errOut,
   936         result = rld_load(errOut,
  1122                           (struct mach_header **)0,
   937                           (struct mach_header **)0,
  1123                           files,
   938                           files,
  1124                           (char *)0);
   939                           (char *)0);
  1125         NXClose(errOut);
   940         NXClose(errOut);
  1126         if (! result) {
   941         if (! result) {
  1127             printf("rld_load %s failed\n", _stringVal(pathName));
   942             fprintf(stderr, "rld_load %s failed\n", _stringVal(pathName));
  1128             RETURN (nil);
   943             RETURN (nil);
  1129         }
   944         }
  1130 
   945 
  1131         printf("rld_load %s ok\n", _stringVal(pathName));
   946         if (ObjectFileLoader_Verbose == true)
       
   947             printf("rld_load %s ok\n", _stringVal(pathName));
  1132         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(1), _MKSMALLINT(1));
   948         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(1), _MKSMALLINT(1));
  1133         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(2), _MKSMALLINT(0));
   949         _AT_PUT_(aBuffer COMMA_SND, _MKSMALLINT(2), _MKSMALLINT(0));
  1134     }
   950     }
  1135 #endif
   951 #endif
  1136 %}.
   952 %}.
  1148         if (dld_unlink_by_file(_stringVal(handle), 1)) {
   964         if (dld_unlink_by_file(_stringVal(handle), 1)) {
  1149             dld_perror("cant unlink");
   965             dld_perror("cant unlink");
  1150         }
   966         }
  1151         RETURN ( self );
   967         RETURN ( self );
  1152     }
   968     }
       
   969     RETURN (self);
  1153 #endif
   970 #endif
  1154 %}.
   971 %}.
  1155 
   972 
  1156     hi := handle at:1.
   973     hi := handle at:1.
  1157     low := handle at:2.
   974     low := handle at:2.
  1162     int val;
   979     int val;
  1163 
   980 
  1164     if (_isSmallInteger(low) && _isSmallInteger(hi)) {
   981     if (_isSmallInteger(low) && _isSmallInteger(hi)) {
  1165         val = (_intVal(hi) << 16) + _intVal(low);
   982         val = (_intVal(hi) << 16) + _intVal(low);
  1166         h = (void *)(val);
   983         h = (void *)(val);
  1167         printf("close handle = %x\n", h);
   984         if (ObjectFileLoader_Verbose == true)
       
   985             printf("close handle = %x\n", h);
  1168         dlclose(h);
   986         dlclose(h);
  1169     }
   987     }
  1170 #endif
   988 #endif
  1171 
   989 
  1172 #ifdef SUN_DL
   990 #ifdef SUN_DL
  1175     int val;
   993     int val;
  1176 
   994 
  1177     if (_isSmallInteger(low) && _isSmallInteger(hi)) {
   995     if (_isSmallInteger(low) && _isSmallInteger(hi)) {
  1178         val = (_intVal(hi) << 16) + _intVal(low);
   996         val = (_intVal(hi) << 16) + _intVal(low);
  1179         h = (void *)(val);
   997         h = (void *)(val);
  1180         printf("close handle = %x\n", h);
   998         if (ObjectFileLoader_Verbose == true)
       
   999             printf("close handle = %x\n", h);
  1181         dlclose(h);
  1000         dlclose(h);
  1182     }
  1001     }
  1183 #endif
  1002 #endif
  1184 %}
  1003 %}
  1185 !
  1004 !
  1186 
  1005 
  1187 getSymbol:aString from:handle
  1006 isSmalltalkObject:handle
  1188     "return the address of a symbol from a dynamically loaded object file.
  1007     "return true, if the loaded object is a smalltalk object module"
       
  1008 
       
  1009     "not yet implemented - stc_compiled_smalltalk is a static symbol,
       
  1010      not found in list - need nm-interface, or nlist-walker
       
  1011     "
       
  1012     ^ true.
       
  1013 
       
  1014     (self getSymbol:'__stc_compiled_smalltalk' function:true from:handle) notNil ifTrue:[^ true].
       
  1015     (self getSymbol:'__stc_compiled_smalltalk' function:false from:handle) notNil ifTrue:[^ true].
       
  1016     ^ false
       
  1017 !
       
  1018 
       
  1019 isCPlusPlusObject:handle
       
  1020     "return true, if the loaded object is a c++ object module"
       
  1021 
       
  1022     (self getSymbol:'__gnu_compiled_cplusplus' function:true from:handle) notNil ifTrue:[^ true].
       
  1023     (self getSymbol:'__CTOR_LIST__' function:true from:handle) notNil ifTrue:[^ true].
       
  1024     (self getSymbol:'__CTOR_LIST__' function:false from:handle) notNil ifTrue:[^ true].
       
  1025     (self getSymbol:'__gnu_compiled_cplusplus' function:false from:handle) notNil ifTrue:[^ true].
       
  1026     ^ false
       
  1027 !
       
  1028 
       
  1029 namesMatching:aPattern in:aFileName
       
  1030     |p l s addr segment name entry|
       
  1031 
       
  1032     l := OrderedCollection new.
       
  1033     p := PipeStream readingFrom:('nm ' , aFileName).
       
  1034     p isNil ifTrue:[
       
  1035         ('cannot read names from ' , aFileName) errorPrintNL.
       
  1036         ^ nil
       
  1037     ].
       
  1038     [p atEnd] whileFalse:[
       
  1039         entry := p nextLine.
       
  1040         s := ReadStream on:entry.
       
  1041         addr := s nextWord.
       
  1042         segment := s nextWord.
       
  1043         name := s upToEnd withoutSeparators.
       
  1044         (addr notNil and:[segment notNil and:[name notNil]]) ifTrue:[
       
  1045             (aPattern match:name) ifTrue:[
       
  1046                 l add:name
       
  1047             ]
       
  1048         ]
       
  1049     ].
       
  1050     p close.
       
  1051     ^ l
       
  1052 !
       
  1053 
       
  1054 isObjectiveCObject:handle
       
  1055     "not yet implemented"
       
  1056 
       
  1057     ^ false
       
  1058 !
       
  1059 
       
  1060 getFunction:aString from:handle
       
  1061     "return the address of a function from a dynamically loaded object file.
       
  1062      Handle must be the one returned previously from openDynamicObject.
       
  1063      Return the address of the function, or nil on any error."
       
  1064 
       
  1065     ^ self getSymbol:aString function:true from:handle
       
  1066 !
       
  1067 
       
  1068 getSymbol:aString function:isFunction from:handle
       
  1069     "return the address of a symbol/function from a dynamically loaded object file.
  1189      Handle must be the one returned previously from openDynamicObject.
  1070      Handle must be the one returned previously from openDynamicObject.
  1190      Return the address of the symbol, or nil on any error."
  1071      Return the address of the symbol, or nil on any error."
  1191 
  1072 
  1192     |low hi lowAddr hiAddr|
  1073     |low hi lowAddr hiAddr|
  1193 
  1074 
  1194 %{
  1075 %{  /* STACK: 20000 */
       
  1076 
  1195 #ifdef GNU_DL
  1077 #ifdef GNU_DL
  1196 #   include "dld.h"
  1078 #   include "dld.h"
  1197     void (*func)();
  1079     void (*func)();
       
  1080     unsigned long addr;
       
  1081     char *name;
  1198 
  1082 
  1199     if (__isString(aString)) {
  1083     if (__isString(aString)) {
  1200         func = (void (*) ()) dld_get_func(_stringVal(aString));
  1084         name = (char *) _stringVal(aString);
  1201         if (func) {
  1085         if (isFunction == false) {
  1202             printf("addr = %x\n", (INT)func);
  1086             addr = dld_get_symbol(name);
  1203             lowAddr = _MKSMALLINT( (INT)func & 0xFFFF );
       
  1204             hiAddr = _MKSMALLINT( ((INT)func >> 16) & 0xFFFF );
       
  1205         } else {
  1087         } else {
  1206             dld_perror("get_func");
  1088             func = (void (*) ()) dld_get_func(name);
       
  1089             if (func) {
       
  1090                 if (ObjectFileLoader_Verbose == true)
       
  1091                     printf("addr of %s = %x\n", name, (INT)func);
       
  1092                 if (dld_function_executable_p(name)) {
       
  1093                     lowAddr = _MKSMALLINT( (INT)func & 0xFFFF );
       
  1094                     hiAddr = _MKSMALLINT( ((INT)func >> 16) & 0xFFFF );
       
  1095                 } else {
       
  1096                     char **undefNames;
       
  1097                     char **nm;
       
  1098                     int i;
       
  1099         
       
  1100                     if (ObjectFileLoader_Verbose == true) {
       
  1101                         printf ("function %s not executable\n", name);
       
  1102                         dld_perror("not executable");
       
  1103                     
       
  1104                         printf("undefined:\n");
       
  1105                         nm = undefNames = dld_list_undefined_sym();
       
  1106                         for (i=dld_undefined_sym_count; i; i--) {
       
  1107                             printf("    %s\n", *nm++);
       
  1108                         }
       
  1109                     }
       
  1110                     free(undefNames);
       
  1111                 }
       
  1112             } else {
       
  1113                 dld_perror("get_func");
       
  1114             }
  1207         }
  1115         }
  1208     }
  1116     }
  1209 #endif
  1117 #endif
  1210 %}.
  1118 %}.
  1211 
  1119 
  1220 
  1128 
  1221     if (_isSmallInteger(low) && _isSmallInteger(hi)) {
  1129     if (_isSmallInteger(low) && _isSmallInteger(hi)) {
  1222         val = (_intVal(hi) << 16) + _intVal(low);
  1130         val = (_intVal(hi) << 16) + _intVal(low);
  1223         h = (void *)(val);
  1131         h = (void *)(val);
  1224         if (__isString(aString)) {
  1132         if (__isString(aString)) {
  1225             printf("get sym <%s> handle = %x\n", _stringVal(aString), h);
  1133             if (ObjectFileLoader_Verbose == true)
       
  1134                 printf("get sym <%s> handle = %x\n", _stringVal(aString), h);
  1226             addr = dlsym(h, _stringVal(aString));
  1135             addr = dlsym(h, _stringVal(aString));
  1227             if (addr) {
  1136             if (addr) {
  1228                 printf("addr = %x\n", addr);
  1137                 if (ObjectFileLoader_Verbose == true)
       
  1138                     printf("addr = %x\n", addr);
  1229                 lowAddr = _MKSMALLINT( (int)addr & 0xFFFF );
  1139                 lowAddr = _MKSMALLINT( (int)addr & 0xFFFF );
  1230                 hiAddr = _MKSMALLINT( ((int)addr >> 16) & 0xFFFF );
  1140                 hiAddr = _MKSMALLINT( ((int)addr >> 16) & 0xFFFF );
  1231             } else {
  1141             } else {
  1232                 printf("dlsym %s error: <%s>\n", _stringVal(aString), dlerror());
  1142                 if (ObjectFileLoader_Verbose == true)
       
  1143                     printf("dlsym %s error: <%s>\n", _stringVal(aString), dlerror());
  1233             }
  1144             }
  1234         }
  1145         }
  1235     }
  1146     }
  1236 #endif
  1147 #endif
  1237 
  1148 
  1243 
  1154 
  1244     if (_isSmallInteger(low) && _isSmallInteger(hi)) {
  1155     if (_isSmallInteger(low) && _isSmallInteger(hi)) {
  1245         val = (_intVal(hi) << 16) + _intVal(low);
  1156         val = (_intVal(hi) << 16) + _intVal(low);
  1246         h = (void *)(val);
  1157         h = (void *)(val);
  1247         if (__isString(aString)) {
  1158         if (__isString(aString)) {
  1248             printf("get sym <%s> handle = %x\n", _stringVal(aString), h);
  1159             if (ObjectFileLoader_Verbose == true)
       
  1160                 printf("get sym <%s> handle = %x\n", _stringVal(aString), h);
  1249             addr = dlsym(h, _stringVal(aString));
  1161             addr = dlsym(h, _stringVal(aString));
  1250             if (addr) {
  1162             if (addr) {
  1251                 printf("addr = %x\n", addr);
  1163                 if (ObjectFileLoader_Verbose == true)
       
  1164                     printf("addr = %x\n", addr);
  1252                 lowAddr = _MKSMALLINT( (int)addr & 0xFFFF );
  1165                 lowAddr = _MKSMALLINT( (int)addr & 0xFFFF );
  1253                 hiAddr = _MKSMALLINT( ((int)addr >> 16) & 0xFFFF );
  1166                 hiAddr = _MKSMALLINT( ((int)addr >> 16) & 0xFFFF );
  1254             } else {
  1167             } else {
  1255                 printf("dlsym %s error: <%s>\n", _stringVal(aString), dlerror());
  1168                 if (ObjectFileLoader_Verbose == true)
       
  1169                     printf("dlsym %s error: <%s>\n", _stringVal(aString), dlerror());
  1256             }
  1170             }
  1257         }
  1171         }
  1258     }
  1172     }
  1259 #endif
  1173 #endif
  1260 
  1174 
  1262     unsigned long addr;
  1176     unsigned long addr;
  1263     long result;
  1177     long result;
  1264     NXStream *errOut;
  1178     NXStream *errOut;
  1265 
  1179 
  1266     if (__isString(aString)) {
  1180     if (__isString(aString)) {
  1267         printf("get sym <%s>\n", _stringVal(aString));
  1181         if (ObjectFileLoader_Verbose == true)
       
  1182             printf("get sym <%s>\n", _stringVal(aString));
  1268         errOut = NXOpenFile(2, 2);
  1183         errOut = NXOpenFile(2, 2);
  1269         result = rld_lookup(errOut,
  1184         result = rld_lookup(errOut,
  1270                             (char *) _stringVal(aString),
  1185                             (char *) _stringVal(aString),
  1271                             &addr);
  1186                             &addr);
  1272         NXClose(errOut);
  1187         NXClose(errOut);
  1273         if (result) {
  1188         if (result) {
  1274             printf("addr = %x\n", addr);
  1189             if (ObjectFileLoader_Verbose == true)
       
  1190                 printf("addr = %x\n", addr);
  1275             lowAddr = _MKSMALLINT( (int)addr & 0xFFFF );
  1191             lowAddr = _MKSMALLINT( (int)addr & 0xFFFF );
  1276             hiAddr = _MKSMALLINT( ((int)addr >> 16) & 0xFFFF );
  1192             hiAddr = _MKSMALLINT( ((int)addr >> 16) & 0xFFFF );
  1277         }
  1193         }
  1278     }
  1194     }
  1279 #endif
  1195 #endif
  1283         ^ (hiAddr * 16r10000) + lowAddr
  1199         ^ (hiAddr * 16r10000) + lowAddr
  1284     ].
  1200     ].
  1285     ^ nil
  1201     ^ nil
  1286 !
  1202 !
  1287 
  1203 
       
  1204 getListOfUndefinedSymbolsFrom:handle
       
  1205     "return a collection of undefined symbols in a dynamically loaded object file.
       
  1206      Handle must be the one returned previously from openDynamicObject."
       
  1207 
       
  1208     |list|
       
  1209 
       
  1210     list := Array new:100. "no more than 100 symbols"
       
  1211 %{ 
       
  1212 
       
  1213 #ifdef GNU_DL
       
  1214 #   include "dld.h"
       
  1215     void (*func)();
       
  1216     unsigned long addr;
       
  1217     char *name;
       
  1218     int nMax;
       
  1219 
       
  1220     if (__isArray(list)) {
       
  1221         char **undefNames;
       
  1222         char **nm;
       
  1223         int index;
       
  1224 
       
  1225         nMax = _arraySize(list);
       
  1226 
       
  1227         nm = undefNames = dld_list_undefined_sym();
       
  1228         for (index = 0; index < dld_undefined_sym_count; index++) {
       
  1229             _ArrayInstPtr(list)->a_element[index] = _MKSTRING(*nm++);
       
  1230             if (index == nMax)
       
  1231                 break;
       
  1232         }
       
  1233         free(undefNames);
       
  1234     }
       
  1235 #endif
       
  1236 
       
  1237 #ifdef SYSV4_DL
       
  1238     /*
       
  1239      * dont know how to do it
       
  1240      */
       
  1241 #endif
       
  1242 
       
  1243 #ifdef SUN_DL
       
  1244     /*
       
  1245      * dont know how to do it
       
  1246      */
       
  1247 #endif
       
  1248 
       
  1249 #ifdef NEXT_DL
       
  1250     /*
       
  1251      * dont know how to do it
       
  1252      */
       
  1253 #endif
       
  1254 %}.
       
  1255     ^ list
       
  1256 !
       
  1257 
  1288 releaseSymbolTable
  1258 releaseSymbolTable
  1289     "this is needed on NeXT to forget loaded names. If this wasnt done,
  1259     "this is needed on NeXT to forget loaded names. If this wasnt done,
  1290      the same class could not be loaded in again due to multiple defines.
  1260      the same class could not be loaded in again due to multiple defines.
  1291      On other architectures, this is not needed and therefore a noop."
  1261      On other architectures, this is not needed and therefore a noop."
  1292 
  1262 
  1300     NXClose(errOut);
  1270     NXClose(errOut);
  1301 #endif
  1271 #endif
  1302 %}
  1272 %}
  1303 !
  1273 !
  1304 
  1274 
  1305 callFunctionAt:address
  1275 callInitFunctionAt:initAddr
       
  1276     "
       
  1277      need 3 passes to init: 1: create my pools
       
  1278                             2: get var-refs to other pools
       
  1279                             3: install class, methods and literals
       
  1280     "
       
  1281     self callFunctionAt:initAddr forceOld:true arg:0.
       
  1282     self callFunctionAt:initAddr forceOld:true arg:1.
       
  1283     self callFunctionAt:initAddr forceOld:true arg:2.
       
  1284 !
       
  1285 
       
  1286 callFunctionAt:address forceOld:forceOld arg:argument
  1306     "call a function at address - this is very dangerous.
  1287     "call a function at address - this is very dangerous.
  1307      This is needed to call the classes init-function after loading in a
  1288      This is needed to call the classes init-function after loading in a
  1308      class-object file. Dont use in your programs."
  1289      class-object file. Dont use in your programs."
  1309 
  1290 
  1310     |low hi lowAddr hiAddr|
  1291     |low hi lowAddr hiAddr|
  1315     void (*addr)();
  1296     void (*addr)();
  1316     unsigned val;
  1297     unsigned val;
  1317     typedef void (*VOIDFUNC)();
  1298     typedef void (*VOIDFUNC)();
  1318     int savInt;
  1299     int savInt;
  1319     extern int _immediateInterrupt;
  1300     extern int _immediateInterrupt;
       
  1301     int prevSpace;
       
  1302     int arg = 0;
  1320 
  1303 
  1321     if (_isSmallInteger(low) && _isSmallInteger(hi)) {
  1304     if (_isSmallInteger(low) && _isSmallInteger(hi)) {
  1322         val = (_intVal(hi) << 16) + _intVal(low);
  1305         val = (_intVal(hi) << 16) + _intVal(low);
  1323         addr = (VOIDFUNC) val;
  1306         addr = (VOIDFUNC) val;
  1324 
  1307 
       
  1308         if (_isSmallInteger(argument)) {
       
  1309             arg = _intVal(argument);
       
  1310         }
  1325         /*
  1311         /*
  1326          * allow function to be interrupted
  1312          * allow function to be interrupted
  1327          */
  1313          */
  1328         savInt = _immediateInterrupt;
  1314         savInt = _immediateInterrupt;
  1329         _immediateInterrupt = 1;
  1315         _immediateInterrupt = 1;
  1330 
  1316 
  1331         (*addr)();
  1317         if (forceOld == true) {
       
  1318             prevSpace = allocForceSpace(OLDSPACE);
       
  1319             (*addr)(arg);
       
  1320             allocForceSpace(prevSpace);
       
  1321         } else {
       
  1322             (*addr)(arg);
       
  1323         }
  1332 
  1324 
  1333         _immediateInterrupt = savInt;
  1325         _immediateInterrupt = savInt;
  1334     }
  1326     }
  1335 %}
  1327 %}
  1336 ! !
  1328 ! !
  1337 
  1329 
       
  1330 !ObjectFileLoader class methodsFor:'primitive loading'!
       
  1331 
       
  1332 textSizeOf:aFileName
       
  1333     "
       
  1334      get the size of the text-segment (nBytes)
       
  1335     "
       
  1336 
       
  1337 %{  /* NOCONTEXT */
       
  1338 #ifdef HAS_DL
       
  1339     /*
       
  1340      * not needed, if dynamic link facilities exist
       
  1341      */
       
  1342 #else /* no DL-support */
       
  1343     char *fname;
       
  1344     int fd;
       
  1345 
       
  1346     if (! __isString(aFileName)) {
       
  1347         RETURN (nil);
       
  1348     }
       
  1349 
       
  1350     fname = (char *) _stringVal(aFileName);
       
  1351 
       
  1352 # if defined(A_DOT_OUT) && !defined(ELF)
       
  1353 #  if !defined(sco) && !defined(isc)
       
  1354     {
       
  1355         struct exec header;
       
  1356 
       
  1357         if ((fd = open(fname, 0)) < 0) {
       
  1358             fprintf(stderr, "cannot open <%s>\n", fname);
       
  1359             RETURN ( nil );
       
  1360         }
       
  1361         if (read(fd, &header, sizeof(header)) != sizeof(header)) {
       
  1362             fprintf(stderr, "cannot read header of <%s>\n", fname);
       
  1363             close(fd);
       
  1364             RETURN ( nil );
       
  1365         }
       
  1366         close(fd);
       
  1367 
       
  1368         if (N_MAGIC(header) != OMAGIC) {
       
  1369             fprintf(stderr, "header is (0%o) %x - should be (0%o)%x\n",
       
  1370                                         N_MAGIC(header), N_MAGIC(header),
       
  1371                                         OMAGIC, OMAGIC);
       
  1372             RETURN ( nil );
       
  1373         }
       
  1374         RETURN ( _MKSMALLINT(header.a_text) );
       
  1375     }
       
  1376 #  endif
       
  1377 # endif
       
  1378     /*
       
  1379      * need support for other headers ... (i.e. coff, elf)
       
  1380      */
       
  1381 #endif
       
  1382 %}.
       
  1383     ^ self error:'objectFile format not supported'
       
  1384 !
       
  1385 
       
  1386 dataSizeOf:aFileName
       
  1387     "
       
  1388      get the size of the data-segment (nBytes)
       
  1389     "
       
  1390 
       
  1391 %{  /* NOCONTEXT */
       
  1392 #ifdef HAS_DL
       
  1393     /*
       
  1394      * not needed, if dynamic link facilities exist
       
  1395      */
       
  1396 #else /* no DL-support */
       
  1397     char *fname;
       
  1398     int fd;
       
  1399 
       
  1400     if (! __isString(aFileName)) {
       
  1401         RETURN ( nil );
       
  1402     }
       
  1403 
       
  1404     fname = (char *) _stringVal(aFileName);
       
  1405 
       
  1406 # if defined(A_DOT_OUT) && !defined(ELF)
       
  1407 #  if !defined(sco) && !defined(isc)
       
  1408     {
       
  1409         struct exec header;
       
  1410         unsigned size;
       
  1411 
       
  1412         if ((fd = open(fname, 0)) < 0) {
       
  1413             fprintf(stderr, "cannot open <%s>\n", fname);
       
  1414             RETURN ( nil );
       
  1415         }
       
  1416         if (read(fd, &header, sizeof(header)) != sizeof(header)) {
       
  1417             fprintf(stderr, "cannot read header of <%s>\n", fname);
       
  1418             close(fd);
       
  1419             RETURN ( nil );
       
  1420         }
       
  1421         close(fd);
       
  1422 
       
  1423         if (N_MAGIC(header) != OMAGIC) {
       
  1424             fprintf(stderr, "header is (0%o) %x - should be (0%o)%x\n",
       
  1425                                         N_MAGIC(header), N_MAGIC(header),
       
  1426                                         OMAGIC, OMAGIC);
       
  1427             RETURN ( nil );
       
  1428         }
       
  1429         size = header.a_data;
       
  1430 #   if defined(sinix) && defined(BSD)
       
  1431         size += header.a_bss;
       
  1432 #   endif
       
  1433         RETURN ( _MKSMALLINT(size) );
       
  1434     }
       
  1435 #  endif
       
  1436 # endif
       
  1437     /*
       
  1438      * need support for other headers ... (i.e. coff, elf)
       
  1439      */
       
  1440 #endif
       
  1441 %}
       
  1442 .
       
  1443     ^ self error:'objectFile format not supported'
       
  1444 !
       
  1445 
       
  1446 loadObjectFile:aFileName textAddr:textAddr textSize:textSize
       
  1447                          dataAddr:dataAddr dataSize:dataSize
       
  1448 
       
  1449     "the object in aFileName must have been linked for
       
  1450      absolute address textAddr/dataAddr (using ld -A).
       
  1451      Load the contents from the file. Memory must have previously
       
  1452      been allocated using ExternalBytes."
       
  1453 
       
  1454 %{  /* NOCONTEXT */
       
  1455 #ifdef HAS_DL
       
  1456     /*
       
  1457      * not needed, if dynamic link facilities exist
       
  1458      */
       
  1459 #else /* no DL-support */
       
  1460     if (! __isString(aFileName)) {
       
  1461         RETURN ( nil );
       
  1462     }
       
  1463 
       
  1464 # if defined(A_DOT_OUT) && !defined(ELF)
       
  1465 #  if !defined(sco) && !defined(isc)
       
  1466     {
       
  1467         char *fname = (char *) _stringVal(aFileName);
       
  1468         unsigned taddr, daddr;
       
  1469         unsigned tsize, dsize;
       
  1470         unsigned toffset = 0;
       
  1471         unsigned doffset = 0;
       
  1472         int fd;
       
  1473         struct exec header;
       
  1474         char *cp;
       
  1475         int bssCount;
       
  1476         unsigned magic = OMAGIC;
       
  1477         int nread;
       
  1478 
       
  1479         taddr = _isSmallInteger(textAddr) ? (unsigned) _intVal(textAddr) : 0;
       
  1480         daddr = _isSmallInteger(dataAddr) ? (unsigned) _intVal(dataAddr) : 0;
       
  1481         tsize = _isSmallInteger(textSize) ? _intVal(textSize) : 0;
       
  1482         dsize = _isSmallInteger(dataSize) ? _intVal(dataSize) : 0;
       
  1483 
       
  1484         if ((fd = open(fname, 0)) < 0)  {
       
  1485             fprintf(stderr, "cannot open <%s>\n", fname);
       
  1486             RETURN ( nil );
       
  1487         }
       
  1488         if (read(fd, &header, sizeof(header)) != sizeof(header)) {
       
  1489             fprintf(stderr, "cannot read header of <%s>\n", fname);
       
  1490             close(fd);
       
  1491             RETURN ( nil );
       
  1492         }
       
  1493         if (N_MAGIC(header) != magic) {
       
  1494             fprintf(stderr, "header is (0%o) %x should be (0%o) %x\n",
       
  1495                                         N_MAGIC(header), N_MAGIC(header),
       
  1496                                         magic, magic);
       
  1497             close(fd);
       
  1498             RETURN ( nil );
       
  1499         }
       
  1500 
       
  1501         /*
       
  1502          * some linkers produce a huge output file, with zeros up to the
       
  1503          * real code ... - thats what toffset, doffset are for.
       
  1504          */
       
  1505 #   if defined(sinix) && defined(BSD)
       
  1506         toffset = N_TXTADDR(header);
       
  1507         doffset = toffset + taddr + tsize /* - 0x800 */;
       
  1508         daddr = taddr + tsize;
       
  1509 #   else
       
  1510 #    if defined(mips) && defined(ultrix)
       
  1511         toffset = N_TXTOFF(header.ex_f, header.ex_o);
       
  1512         doffset = toffset + tsize;
       
  1513         daddr = taddr + tsize;
       
  1514 #    else
       
  1515 #     if defined(N_TXTOFF)
       
  1516         toffset = N_TXTOFF(header);
       
  1517         doffset = N_DATOFF(header);
       
  1518         daddr = taddr + tsize;
       
  1519 #     else
       
  1520         fprintf(stderr, "dont know text/data offsets in objectfile\n");
       
  1521         RETURN ( nil );
       
  1522 #     endif
       
  1523 #    endif
       
  1524 #   endif
       
  1525 
       
  1526 #   ifdef SUPERDEBUG
       
  1527         printf("toffs:%x taddr:%x tsize:%d doffs:%x daddr:%x dsize:%d\n",
       
  1528                 toffset, taddr, tsize, doffset,daddr, dsize);
       
  1529 #   endif
       
  1530 
       
  1531         if (lseek(fd, (long)toffset, 0) < 0) {
       
  1532             fprintf(stderr, "cannot seek to text\n");
       
  1533             close(fd);
       
  1534             RETURN ( nil );
       
  1535         }
       
  1536         if ((nread = read(fd, taddr, tsize)) != tsize) {
       
  1537             perror("read");
       
  1538             fprintf(stderr, "cannot read text wanted:%d got:%d\n", tsize, nread);
       
  1539             close(fd);
       
  1540             RETURN ( nil );
       
  1541         }
       
  1542 
       
  1543 #   ifdef SUPERDEBUG
       
  1544         printf("1st bytes of text: %02x %02x %02x %02x\n",
       
  1545                 *((char *)taddr) & 0xFF, *((char *)taddr+1) & 0xFF,
       
  1546                 *((char *)taddr+2) & 0xFF, *((char *)taddr+3) & 0xFF);
       
  1547 #   endif
       
  1548 
       
  1549         if (dsize) {
       
  1550             if (lseek(fd, (long)doffset, 0) < 0) {
       
  1551                 fprintf(stderr, "cannot seek to data\n");
       
  1552                 close(fd);
       
  1553                 RETURN ( nil );
       
  1554             }
       
  1555 
       
  1556             if (read(fd, daddr, dsize) != dsize) {
       
  1557                 fprintf(stderr, "cannot read data\n");
       
  1558                 close(fd);
       
  1559                 RETURN ( nil );
       
  1560             }
       
  1561 #   ifdef SUPERDEBUG
       
  1562             {
       
  1563                 char *ptr;
       
  1564                 int i;
       
  1565     
       
  1566                 ptr = (char *)daddr;
       
  1567                 fprintf(stderr, "bytes of data (at %x):\n", ptr);
       
  1568                 for (i=dsize; i>0; i--, ptr++)
       
  1569                     printf("%02x ", *ptr & 0xFF);
       
  1570             }
       
  1571 #   endif
       
  1572         }
       
  1573         close(fd);
       
  1574 
       
  1575 #   ifdef NOTDEF
       
  1576         if (header.a_bss != 0) {
       
  1577             fprintf(stderr, "warning: bss not empty\n");
       
  1578             cp = ((char *)daddr) + header.a_data;
       
  1579             for (bssCount=header.a_bss; bssCount; bssCount--)
       
  1580                 *cp++ = 0;
       
  1581         }
       
  1582 #   endif
       
  1583     }
       
  1584     RETURN ( self );
       
  1585 #  endif
       
  1586 # endif
       
  1587     /*
       
  1588      * need support for other headers ... (i.e. coff, elf)
       
  1589      */
       
  1590 #endif
       
  1591 %}.
       
  1592     ^ self error:'objectFile format not supported'
       
  1593 ! !
       
  1594 
  1338 ObjectFileLoader initialize!
  1595 ObjectFileLoader initialize!