Changeset 186

Show
Ignore:
Timestamp:
05/02/06 18:18:20 (3 years ago)
Author:
larsivi
Message:

Fixed a minor bug, added some debug output, somehow the magic header of the elf files has disappeared.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ddl/ar/ArchiveLibrary.d

    r176 r186  
    11/+ 
    2    Copyright (c) 2005 Lars Ivar Igesund, J Duncan, Eric Anderton 
    3  
    4    Permission is hereby granted, free of charge, to any person 
    5    obtaining a copy of this software and associated documentation 
    6    files (the "Software"), to deal in the Software without 
    7    restriction, including without limitation the rights to use, 
    8    copy, modify, merge, publish, distribute, sublicense, and/or 
    9    sell copies of the Software, and to permit persons to whom the 
    10    Software is furnished to do so, subject to the following 
    11    conditions: 
    12  
    13    The above copyright notice and this permission notice shall be 
    14    included in all copies or substantial portions of the Software. 
    15  
    16    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
    17    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
    18    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
    19    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
    20    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
    21    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
    22    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
    23    OTHER DEALINGS IN THE SOFTWARE. 
     2    Copyright (c) 2005 Lars Ivar Igesund, J Duncan, Eric Anderton 
     3 
     4    Permission is hereby granted, free of charge, to any person 
     5    obtaining a copy of this software and associated documentation 
     6    files (the "Software"), to deal in the Software without 
     7    restriction, including without limitation the rights to use, 
     8    copy, modify, merge, publish, distribute, sublicense, and/or 
     9    sell copies of the Software, and to permit persons to whom the 
     10    Software is furnished to do so, subject to the following 
     11    conditions: 
     12 
     13    The above copyright notice and this permission notice shall be 
     14    included in all copies or substantial portions of the Software. 
     15 
     16    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
     17    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
     18    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
     19    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
     20    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
     21    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
     22    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
     23    OTHER DEALINGS IN THE SOFTWARE. 
    2424+/ 
    2525module ddl.ar.ArchiveLibrary; 
     
    4949 
    5050class ArchiveReader : DDLReader{ 
    51    public this(IBuffer buffer){ 
    52        super(buffer); 
    53    
    54      
    55    alias DDLReader.get get; 
    56  
    57    public ArchiveReader get(inout ArchiveHeader arh){ 
    58        super.read(&arh,ArchiveHeader.sizeof,0); 
    59        return this; 
    60    
     51    public this(IBuffer buffer){ 
     52        super(buffer); 
     53   
     54     
     55    alias DDLReader.get get; 
     56 
     57    public ArchiveReader get(inout ArchiveHeader arh){ 
     58        super.read(&arh,ArchiveHeader.sizeof,0); 
     59        return this; 
     60   
    6161} 
    6262 
    6363class ArchiveLibrary : DynamicLibrary{ 
    64    const char[] ARCHID = "!<arch>\n"; 
    65    const char[] ARFMAG = "`\n"; 
    66      
    67    /* TODO: For future use, that is when we start using the symboltable.  
    68       larsivi 20060101 
    69      
    70    struct Symbol{ 
    71            uint offset; 
    72            ubyte[] name; 
    73    
    74     */   
    75      
    76    private int exportsready = 0; 
    77    private LoaderRegistry registry = null; 
    78    private char[] stringtable; 
     64    const char[] ARCHID = "!<arch>\n"; 
     65    const char[] ARFMAG = "`\n"; 
     66     
     67    /* TODO: For future use, that is when we start using the symboltable.  
     68       larsivi 20060101 
     69     
     70    struct Symbol{ 
     71            uint offset; 
     72            ubyte[] name; 
     73   
     74    */   
     75     
     76    private int exportsready = 0; 
     77    private LoaderRegistry registry = null; 
     78    private char[] stringtable; 
    7979    private DynamicModule [] modules; 
    8080    private ExportSymbol [char[]] exports; 
    8181 
    82         public this(LoaderRegistry registry, FileBuffer file){ 
    83                 this.registry = registry; 
    84                 load(file); 
    85         } 
    86          
    87         public void loadSymbolTable(char [] symtable, uint size){ 
    88                 // TODO: Do something sensible about this 
    89                 // I suppose it wouldn't be in the archive at all 
    90                 // unless some optimizing scheme could be devised. 
    91                 // larsivi 20060101 
    92         } 
    93  
    94         public DynamicModule[] getModules(){ 
    95                 return this.modules; 
    96         } 
    97  
    98         private char[] getModuleName(char[] filename){ 
    99                 if(filename[0] == '/'){ 
    100                         uint offset = Atoi.parse(Text.trim(filename[1..$]));  
    101                         return stringtable[offset..Text.indexOf(stringtable[offset..$], "/")+offset]; 
    102                 } 
    103                 else{ 
    104                         return filename[0..Text.indexOf(filename, r"/")]; 
    105                 } 
    106         } 
    107  
    108         private void load(IBuffer buffer){ 
    109             ArchiveReader reader = new ArchiveReader(buffer); 
    110                      
    111             // read the library signature 
    112             int nAddress; 
    113             char[] signature; 
    114             reader.get(signature,ARCHID.length); 
    115              
    116             if((signature.length != ARCHID.length) || (signature != ARCHID)){ 
    117                 throw new Exception("Invalid library signature."); 
    118             } 
     82    public this(LoaderRegistry registry, FileBuffer file){ 
     83        this.registry = registry; 
     84        load(file); 
     85    } 
     86         
     87    public void loadSymbolTable(char [] symtable, uint size){ 
     88        debug debugLog("* Loading symbol table"); 
     89        // TODO: Do something sensible about this 
     90        // I suppose it wouldn't be in the archive at all 
     91        // unless some optimizing scheme could be devised. 
     92        // larsivi 20060101 
     93    } 
     94 
     95    public DynamicModule[] getModules(){ 
     96        return this.modules; 
     97    } 
     98 
     99    private char[] getModuleName(char[] filename){ 
     100        if(filename[0] == '/'){ 
     101            uint offset = Atoi.parse(Text.trim(filename[1..$]));  
     102            return stringtable[offset..Text.indexOf(stringtable[offset..$], "/")+offset]; 
     103        } 
     104        else{ 
     105            return filename[0..Text.indexOf(filename, r"/")]; 
     106        } 
     107    } 
     108 
     109    private void load(IBuffer buffer){ 
     110        ArchiveReader reader = new ArchiveReader(buffer); 
     111                     
     112        // read the library signature 
     113        int nAddress; 
     114        char[] signature; 
     115        reader.get(signature,ARCHID.length); 
     116            
     117        if((signature.length != ARCHID.length) || (signature != ARCHID)){ 
     118            throw new Exception("Invalid library signature."); 
     119        } 
    119120          
    120          // read the remaining records 
    121             while(reader.hasMore){ 
    122                 void alignReader(){ 
    123                     if(reader.getPosition & 1){ 
    124                         debug debugLog("* padding data address"); 
    125                         ubyte dummy; 
    126                         reader.get(dummy); 
    127                     } 
    128                 } 
    129                 alignReader(); 
    130                 if(!reader.hasMore()) break; // re-alignment may cause EOF 
    131  
    132                 // read member header 
    133                 ArchiveHeader hdr; 
    134                 reader.get(hdr);  // throws "illegal library file"  
    135                 //assert( hdr.ar_fmag == ARFMAG ); 
    136                  
    137                 if( hdr.ar_fmag != ARFMAG ){ 
    138                     throw new DDLException("Invalid link member signature: %d\n",hdr.ar_fmag[1]); 
    139                 } 
    140  
    141                 char [] fName = Text.trim(hdr.ar_name); 
    142                 uint fSize = Atoi.parse(Text.trim(hdr.ar_size)); 
    143                              
    144                 // read member data 
    145                 char[] memberData; 
    146                 reader.get(memberData,fSize); 
    147      
    148                 switch(fName){ 
    149                 case "/": 
    150                     // Need to check the next header 
    151                    // If it has the same name, it is a 
    152                    // PECOFF lib, otherwise it's an Ar-lib 
    153                    ArchiveHeader tmphdr; 
    154                    reader.get(tmphdr); 
    155                                      
    156                    if (Text.trim(tmphdr.ar_name) == "/") { 
    157                     // PECOFF archive 
    158                       fSize = Atoi.parse(Text.trim(tmphdr.ar_size)); 
    159                       reader.get(memberData,fSize); 
    160                       loadSymbolTable(memberData,fSize); 
    161                    } 
    162                    else {  // Ar 
    163                     // Step back to previous pos 
    164      
    165                       // WORKAROUND: I have no idea 
    166                       // what happens here, if I use 
    167                       // the AH.sizeof directly in seek 
    168                       // it seems to use seekEnd 
    169                       // instead. larsivi 20060101 
    170                       int len = ArchiveHeader.sizeof; 
    171                       reader.seek(-len); 
    172                       loadSymbolTable(memberData,fSize); 
    173                    } 
    174                    break; 
    175                 case "//": 
    176                    stringtable.length = fSize; 
    177                    assert (stringtable.length == memberData.length); 
    178                    stringtable = memberData; 
    179                    break; 
    180                 default: // The rest 
    181                    FileBuffer embeddedFile = new FileBuffer(getModuleName(fName),memberData); 
    182                    DynamicLibrary dl = this.registry.load(embeddedFile); 
    183                    addModules(dl.getModules()); 
    184                    break; 
    185                 } 
    186             } 
    187         } 
    188  
    189     public ExportSymbol[] getExports(){ 
    190                 return exports.values; 
    191         } 
    192          
    193     public ExportSymbol getExport(char[] name){ 
    194                 if (name in exports){ 
    195                         return exports[name]; 
    196                 } 
    197                 else { 
    198                         return ExportSymbol.NONE; 
    199                 } 
    200         } 
    201          
    202         public char[] getType(){ 
    203             return "Archive"; 
    204         } 
    205  
    206         public char[][char[]] getAttributes(){ 
    207             return null; 
    208         } 
    209  
    210         //TODO: implement me         
    211         public DynamicModule getModuleForExport(char[] name){ 
    212             return null; 
    213         } 
    214          
    215         //TODO: implement me 
    216         public ubyte[] getResource(char[] name){ 
    217             return (ubyte[]).init; 
    218         }         
    219  
    220         private void addModules(DynamicModule[] modules){ 
    221                 if (!exportsready){ 
    222                         foreach(DynamicModule dm; modules){ 
    223                                 foreach(ExportSymbol es; 
    224                                                 dm.getExports()){ 
    225                                         exports[es.name] = es; 
    226                                 } 
    227                         } 
    228                 } 
    229                 this.modules ~= modules; 
    230         } 
     121        // read the remaining records 
     122        while(reader.hasMore){ 
     123             
     124            void alignReader(){ 
     125                if(reader.getPosition & 1){ 
     126                    debug debugLog("* padding data address"); 
     127                    ubyte dummy; 
     128                    reader.get(dummy); 
     129                } 
     130            } 
     131         
     132            alignReader(); 
     133            if(!reader.hasMore()) break; // re-alignment may cause EOF 
     134 
     135            // read member header 
     136            ArchiveHeader hdr; 
     137            reader.get(hdr);  // throws "illegal library file"  
     138            //assert( hdr.ar_fmag == ARFMAG ); 
     139                 
     140            if( hdr.ar_fmag != ARFMAG ){ 
     141                throw new DDLException("Invalid link member signature: %d\n",hdr.ar_fmag[1]); 
     142            } 
     143 
     144            char [] fName = Text.trim(hdr.ar_name); 
     145            uint fSize = Atoi.parse(Text.trim(hdr.ar_size)); 
     146 
     147            // read member data 
     148            char[] memberData; 
     149            reader.get(memberData,fSize); 
     150     
     151            switch(fName){ 
     152            case "/": 
     153                // Need to check the next header 
     154                // If it has the same name, it is a 
     155                // PECOFF lib, otherwise it's an Ar-lib 
     156                ArchiveHeader tmphdr; 
     157                reader.get(tmphdr); 
     158                                     
     159                if (Text.trim(tmphdr.ar_name) == "/") { 
     160                    // PECOFF archive 
     161                    fSize = Atoi.parse(Text.trim(tmphdr.ar_size)); 
     162                    reader.get(memberData,fSize); 
     163                    loadSymbolTable(memberData,fSize); 
     164                } 
     165                else {  // Ar 
     166                    // Step back to previous pos 
     167     
     168                    // WORKAROUND: I have no idea 
     169                    // what happens here, if I use 
     170                    // the AH.sizeof directly in seek 
     171                    // it seems to use seekEnd 
     172                    // instead. larsivi 20060101 
     173                    int len = ArchiveHeader.sizeof; 
     174                    reader.seek(reader.getPosition() - len); 
     175                    loadSymbolTable(memberData,fSize); 
     176                } 
     177                break; 
     178            case "//": 
     179                debug debugLog("* String table found in archive"); 
     180                stringtable.length = fSize; 
     181                assert (stringtable.length == memberData.length); 
     182                stringtable = memberData; 
     183                break; 
     184            default: // The rest 
     185                debug debugLog("* Loading module %s from archive", getModuleName(fName)); 
     186                debug debugLog("* file starts with: ", memberData[0..4]); 
     187                FileBuffer embeddedFile = new FileBuffer(getModuleName(fName),memberData); 
     188                DynamicLibrary dl = this.registry.load(embeddedFile); 
     189                addModules(dl.getModules()); 
     190                break; 
     191            } 
     192        } 
     193    } 
     194 
     195    public ExportSymbol[] getExports(){ 
     196        return exports.values; 
     197    } 
     198         
     199    public ExportSymbol getExport(char[] name){ 
     200        if (name in exports){ 
     201            return exports[name]; 
     202        } 
     203        else { 
     204            return ExportSymbol.NONE; 
     205        } 
     206    } 
     207         
     208    public char[] getType(){ 
     209        return "Archive"; 
     210    } 
     211 
     212    public char[][char[]] getAttributes(){ 
     213        return null; 
     214    } 
     215 
     216    //TODO: implement me         
     217    public DynamicModule getModuleForExport(char[] name){ 
     218        return null; 
     219    } 
     220         
     221    //TODO: implement me 
     222    public ubyte[] getResource(char[] name){ 
     223        return (ubyte[]).init; 
     224    }         
     225 
     226    private void addModules(DynamicModule[] modules){ 
     227        if (!exportsready){ 
     228            foreach(DynamicModule dm; modules){ 
     229                foreach(ExportSymbol es; dm.getExports()){ 
     230                    exports[es.name] = es; 
     231                } 
     232            } 
     233        } 
     234        this.modules ~= modules; 
     235    } 
    231236 
    232237}