LCOV - code coverage report
Current view: top level - codemaker/source/javamaker - classfile.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 472 498 94.8 %
Date: 2015-06-13 12:38:46 Functions: 68 69 98.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "classfile.hxx"
      22             : 
      23             : #include "codemaker/global.hxx"
      24             : #include "codemaker/options.hxx"
      25             : #include "codemaker/unotype.hxx"
      26             : 
      27             : #include "osl/diagnose.h"
      28             : #include "rtl/string.h"
      29             : #include "rtl/string.hxx"
      30             : #include "sal/types.h"
      31             : 
      32             : #include <map>
      33             : #include <utility>
      34             : #include <vector>
      35             : 
      36             : using codemaker::javamaker::ClassFile;
      37             : 
      38             : namespace {
      39             : 
      40     1927351 : void appendU1(std::vector< unsigned char > & stream, sal_uInt8 data) {
      41     1927351 :     stream.push_back(static_cast< unsigned char >(data));
      42     1927351 : }
      43             : 
      44      327965 : void appendU2(std::vector< unsigned char > & stream, sal_uInt16 data) {
      45      327965 :     stream.push_back(static_cast< unsigned char >(data >> 8));
      46      327965 :     stream.push_back(static_cast< unsigned char >(data & 0xFF));
      47      327965 : }
      48             : 
      49       25368 : void appendU4(std::vector< unsigned char > & stream, sal_uInt32 data) {
      50       25368 :     stream.push_back(static_cast< unsigned char >(data >> 24));
      51       25368 :     stream.push_back(static_cast< unsigned char >((data >> 16) & 0xFF));
      52       25368 :     stream.push_back(static_cast< unsigned char >((data >> 8) & 0xFF));
      53       25368 :     stream.push_back(static_cast< unsigned char >(data & 0xFF));
      54       25368 : }
      55             : 
      56          29 : void appendU8(std::vector< unsigned char > & stream, sal_uInt64 data) {
      57          29 :     stream.push_back(static_cast< unsigned char >(data >> 56));
      58          29 :     stream.push_back(static_cast< unsigned char >((data >> 48) & 0xFF));
      59          29 :     stream.push_back(static_cast< unsigned char >((data >> 40) & 0xFF));
      60          29 :     stream.push_back(static_cast< unsigned char >((data >> 32) & 0xFF));
      61          29 :     stream.push_back(static_cast< unsigned char >((data >> 24) & 0xFF));
      62          29 :     stream.push_back(static_cast< unsigned char >((data >> 16) & 0xFF));
      63          29 :     stream.push_back(static_cast< unsigned char >((data >> 8) & 0xFF));
      64          29 :     stream.push_back(static_cast< unsigned char >(data & 0xFF));
      65          29 : }
      66             : 
      67       13366 : void appendStream(
      68             :     std::vector< unsigned char > & stream,
      69             :     std::vector< unsigned char > const & data)
      70             : {
      71       13366 :     stream.insert(stream.end(), data.begin(), data.end());
      72       13366 : }
      73             : 
      74       46762 : void write(FileStream & file, void const * buffer, sal_uInt64 size) {
      75       46762 :     if (!file.write(buffer, size))
      76           0 :         throw CannotDumpException("Error writing file");
      77       46762 : }
      78             : 
      79       32940 : void writeU2(FileStream & file, sal_uInt16 data) {
      80             :     unsigned char buf[] = {
      81       32940 :         static_cast< unsigned char >(data >> 8),
      82       32940 :         static_cast< unsigned char >(data & 0xFF) };
      83       32940 :     write(file, buf, sizeof buf);
      84       32940 : }
      85             : 
      86        3294 : void writeU4(FileStream & file, sal_uInt32 data) {
      87             :     unsigned char buf[] = {
      88        3294 :         static_cast< unsigned char >(data >> 24),
      89        3294 :         static_cast< unsigned char >((data >> 16) & 0xFF),
      90        3294 :         static_cast< unsigned char >((data >> 8) & 0xFF),
      91        9882 :         static_cast< unsigned char >(data & 0xFF) };
      92        3294 :     write(file, buf, sizeof buf);
      93        3294 : }
      94             : 
      95       16470 : void writeStream(FileStream & file, std::vector< unsigned char > const & stream)
      96             : {
      97       16470 :     std::vector< unsigned char >::size_type n = stream.size();
      98             :     static_assert(
      99             :         sizeof (std::vector< unsigned char >::size_type)
     100             :         <= sizeof (sal_uInt64), "must be at most equal in size");
     101             :         // both unsigned integral, so sizeof is a practically sufficient
     102             :         // approximation of std::numeric_limits<T1>::max() <=
     103             :         // std::numeric_limits<T2>::max()
     104       16470 :     if (n != 0) {
     105       10528 :         write(file, &stream[0], static_cast< sal_uInt64 >(n));
     106             :     }
     107       16470 : }
     108             : 
     109             : }
     110             : 
     111        7447 : ClassFile::Code::~Code() {}
     112             : 
     113        8433 : void ClassFile::Code::instrAastore() {
     114             :     // aastore:
     115        8433 :     appendU1(m_code, 0x53);
     116        8433 : }
     117             : 
     118         203 : void ClassFile::Code::instrAconstNull() {
     119             :     // aconst_null:
     120         203 :     appendU1(m_code, 0x01);
     121         203 : }
     122             : 
     123        2367 : void ClassFile::Code::instrAnewarray(OString const & type) {
     124             :     // anewarray <indexbyte1> <indexbyte2>:
     125        2367 :     appendU1(m_code, 0xBD);
     126        2367 :     appendU2(m_code, m_classFile.addClassInfo(type));
     127        2367 : }
     128             : 
     129        2444 : void ClassFile::Code::instrAreturn() {
     130             :     // areturn:
     131        2444 :     appendU1(m_code, 0xB0);
     132        2444 : }
     133             : 
     134         718 : void ClassFile::Code::instrAthrow() {
     135             :     // athrow:
     136         718 :     appendU1(m_code, 0xBF);
     137         718 : }
     138             : 
     139         429 : void ClassFile::Code::instrCheckcast(OString const & type) {
     140             :     // checkcast <indexbyte1> <indexbyte2>:
     141         429 :     appendU1(m_code, 0xC0);
     142         429 :     appendU2(m_code, m_classFile.addClassInfo(type));
     143         429 : }
     144             : 
     145       19885 : void ClassFile::Code::instrDup() {
     146             :     // dup:
     147       19885 :     appendU1(m_code, 0x59);
     148       19885 : }
     149             : 
     150        2277 : void ClassFile::Code::instrGetstatic(
     151             :     OString const & type, OString const & name,
     152             :     OString const & descriptor)
     153             : {
     154             :     // getstatic <indexbyte1> <indexbyte2>:
     155        2277 :     appendU1(m_code, 0xB2);
     156        2277 :     appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
     157        2277 : }
     158             : 
     159          31 : ClassFile::Code::Branch ClassFile::Code::instrIfAcmpne() {
     160             :     // if_acmpne <branchbyte1> <branchbyte2>:
     161          31 :     Branch branch = m_code.size();
     162          31 :     appendU1(m_code, 0xA6);
     163          31 :     appendU2(m_code, 0);
     164          31 :     return branch;
     165             : }
     166             : 
     167          31 : ClassFile::Code::Branch ClassFile::Code::instrIfeq() {
     168             :     // ifeq <branchbyte1> <branchbyte2>:
     169          31 :     Branch branch = m_code.size();
     170          31 :     appendU1(m_code, 0x99);
     171          31 :     appendU2(m_code, 0);
     172          31 :     return branch;
     173             : }
     174             : 
     175         354 : ClassFile::Code::Branch ClassFile::Code::instrIfnull() {
     176             :     // ifnull <branchbyte1> <branchbyte2>:
     177         354 :     Branch branch = m_code.size();
     178         354 :     appendU1(m_code, 0xC6);
     179         354 :     appendU2(m_code, 0);
     180         354 :     return branch;
     181             : }
     182             : 
     183          31 : void ClassFile::Code::instrInstanceof(OString const & type) {
     184             :     // instanceof <indexbyte1> <indexbyte2>:
     185          31 :     appendU1(m_code, 0xC1);
     186          31 :     appendU2(m_code, m_classFile.addClassInfo(type));
     187          31 : }
     188             : 
     189         765 : void ClassFile::Code::instrInvokeinterface(
     190             :     OString const & type, OString const & name,
     191             :     OString const & descriptor, sal_uInt8 args)
     192             : {
     193             :     // invokeinterface <indexbyte1> <indexbyte2> <nargs> 0:
     194         765 :     appendU1(m_code, 0xB9);
     195             :     appendU2(
     196         765 :         m_code, m_classFile.addInterfaceMethodrefInfo(type, name, descriptor));
     197         765 :     appendU1(m_code, args);
     198         765 :     appendU1(m_code, 0);
     199         765 : }
     200             : 
     201       13517 : void ClassFile::Code::instrInvokespecial(
     202             :     OString const & type, OString const & name,
     203             :     OString const & descriptor)
     204             : {
     205             :     // invokespecial <indexbyte1> <indexbyte2>:
     206       13517 :     appendU1(m_code, 0xB7);
     207       13517 :     appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
     208       13517 : }
     209             : 
     210         721 : void ClassFile::Code::instrInvokestatic(
     211             :     OString const & type, OString const & name,
     212             :     OString const & descriptor)
     213             : {
     214             :     // invokestatic <indexbyte1> <indexbyte2>:
     215         721 :     appendU1(m_code, 0xB8);
     216         721 :     appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
     217         721 : }
     218             : 
     219         821 : void ClassFile::Code::instrInvokevirtual(
     220             :     OString const & type, OString const & name,
     221             :     OString const & descriptor)
     222             : {
     223             :     // invokevirtual <indexbyte1> <indexbyte2>:
     224         821 :     appendU1(m_code, 0xB6);
     225         821 :     appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
     226         821 : }
     227             : 
     228           1 : void ClassFile::Code::instrLookupswitch(
     229             :     Code const * defaultBlock,
     230             :     std::list< std::pair< sal_Int32, Code * > > const & blocks)
     231             : {
     232             :     // lookupswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
     233             :     // <defaultbyte4> <npairs1> <npairs2> <npairs3> <npairs4>
     234             :     // <match--offset pairs...>:
     235           1 :     std::list< std::pair< sal_Int32, Code * > >::size_type size = blocks.size();
     236           1 :     if (size > SAL_MAX_INT32) {
     237           0 :         throw CannotDumpException("Lookup-switch too large for Java class file format");
     238             :     }
     239           1 :     Position pos1 = m_code.size();
     240           1 :     appendU1(m_code, 0xAB);
     241           1 :     int pad = (pos1 + 1) % 4;
     242           3 :     for (int i = 0; i < pad; ++i) {
     243           2 :         appendU1(m_code, 0);
     244             :     }
     245           1 :     Position pos2 = pos1 + 1 + pad + 8 + blocks.size() * 8; //FIXME: overflow
     246           1 :     appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1)); //FIXME: overflow
     247           1 :     pos2 += defaultBlock->m_code.size(); //FIXME: overflow
     248           1 :     appendU4(m_code, static_cast< sal_uInt32 >(size));
     249         114 :     for (std::list< std::pair< sal_Int32, Code * > >::const_iterator i(
     250           1 :              blocks.begin());
     251          76 :          i != blocks.end(); ++i)
     252             :     {
     253          37 :         appendU4(m_code, static_cast< sal_uInt32 >(i->first));
     254          37 :         appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1));
     255             :             //FIXME: overflow
     256          37 :         pos2 += i->second->m_code.size(); //FIXME: overflow
     257             :     }
     258           1 :     appendStream(m_code, defaultBlock->m_code);
     259         114 :     for (std::list< std::pair< sal_Int32, Code * > >::const_iterator i(
     260           1 :              blocks.begin());
     261          76 :          i != blocks.end(); ++i)
     262             :     {
     263          37 :         appendStream(m_code, i->second->m_code);
     264             :     }
     265           1 : }
     266             : 
     267       11036 : void ClassFile::Code::instrNew(OString const & type) {
     268             :     // new <indexbyte1> <indexbyte2>:
     269       11036 :     appendU1(m_code, 0xBB);
     270       11036 :     appendU2(m_code, m_classFile.addClassInfo(type));
     271       11036 : }
     272             : 
     273          31 : void ClassFile::Code::instrNewarray(codemaker::UnoType::Sort sort) {
     274             :     OSL_ASSERT(
     275             :         sort >= codemaker::UnoType::SORT_BOOLEAN
     276             :         && sort <= codemaker::UnoType::SORT_CHAR);
     277             :     // newarray <atype>:
     278          31 :     appendU1(m_code, 0xBC);
     279             :     static sal_uInt8 const atypes[codemaker::UnoType::SORT_CHAR] = {
     280             :         0x04, 0x08, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x06, 0x07, 0x05 };
     281          31 :     appendU1(m_code, atypes[sort - 1]);
     282          31 : }
     283             : 
     284         354 : void ClassFile::Code::instrPop() {
     285             :     // pop:
     286         354 :     appendU1(m_code, 0x57);
     287         354 : }
     288             : 
     289        2765 : void ClassFile::Code::instrPutfield(
     290             :     OString const & type, OString const & name,
     291             :     OString const & descriptor)
     292             : {
     293             :     // putfield <indexbyte1> <indexbyte2>:
     294        2765 :     appendU1(m_code, 0xB5);
     295        2765 :     appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
     296        2765 : }
     297             : 
     298        3465 : void ClassFile::Code::instrPutstatic(
     299             :     OString const & type, OString const & name,
     300             :     OString const & descriptor)
     301             : {
     302             :     // putstatic <indexbyte1> <indexbyte2>:
     303        3465 :     appendU1(m_code, 0xB3);
     304        3465 :     appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
     305        3465 : }
     306             : 
     307        4808 : void ClassFile::Code::instrReturn() {
     308             :     // return:
     309        4808 :     appendU1(m_code, 0xB1);
     310        4808 : }
     311             : 
     312          31 : void ClassFile::Code::instrSwap() {
     313             :     // swap:
     314          31 :     appendU1(m_code, 0x5F);
     315          31 : }
     316             : 
     317         194 : void ClassFile::Code::instrTableswitch(
     318             :     Code const * defaultBlock, sal_Int32 low,
     319             :     std::list< Code * > const & blocks)
     320             : {
     321             :     // tableswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
     322             :     // <defaultbyte4> <lowbyte1> <lowbyte2> <lowbyte3> <lowbyte4> <highbyte1>
     323             :     // <highbyte2> <highbyte3> <highbyte4> <jump offsets...>:
     324         194 :     Position pos1 = m_code.size();
     325         194 :     appendU1(m_code, 0xAA);
     326         194 :     int pad = (pos1 + 1) % 4;
     327         582 :     for (int i = 0; i < pad; ++i) {
     328         388 :         appendU1(m_code, 0);
     329             :     }
     330         194 :     std::list< Code * >::size_type size = blocks.size();
     331         194 :     Position pos2 = pos1 + 1 + pad + 12 + size * 4; //FIXME: overflow
     332         194 :     sal_uInt32 defaultOffset = static_cast< sal_uInt32 >(pos2 - pos1);
     333             :         //FIXME: overflow
     334         194 :     appendU4(m_code, defaultOffset);
     335         194 :     pos2 += defaultBlock->m_code.size(); //FIXME: overflow
     336         194 :     appendU4(m_code, static_cast< sal_uInt32 >(low));
     337         194 :     appendU4(m_code, static_cast< sal_uInt32 >(low + (size - 1)));
     338        4485 :     for (std::list< Code * >::const_iterator i(blocks.begin());
     339        2990 :          i != blocks.end(); ++i)
     340             :     {
     341        1301 :         if (*i == 0) {
     342           5 :             appendU4(m_code, defaultOffset);
     343             :         } else {
     344        1296 :             appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1));
     345             :                 //FIXME: overflow
     346        1296 :             pos2 += (*i)->m_code.size(); //FIXME: overflow
     347             :         }
     348             :     }
     349         194 :     appendStream(m_code, defaultBlock->m_code);
     350        4485 :     for (std::list< Code * >::const_iterator i(blocks.begin());
     351        2990 :          i != blocks.end(); ++i)
     352             :     {
     353        1301 :         if (*i != 0) {
     354        1296 :             appendStream(m_code, (*i)->m_code);
     355             :         }
     356             :     }
     357         194 : }
     358             : 
     359       28504 : void ClassFile::Code::loadIntegerConstant(sal_Int32 value) {
     360       28504 :     if (value >= -1 && value <= 5) {
     361             :         // iconst_<i>:
     362       22791 :         appendU1(m_code, static_cast< sal_uInt8 >(0x02 + value + 1));
     363        5713 :     } else if (value >= -128 && value <= 127) {
     364             :         // bipush <byte>:
     365        5377 :         appendU1(m_code, 0x10);
     366        5377 :         appendU1(m_code, static_cast< sal_uInt8 >(value));
     367         336 :     } else if (value >= -32768 && value <= 32767) {
     368             :         // sipush <byte1> <byte2>:
     369         321 :         appendU1(m_code, 0x11);
     370         321 :         appendU2(m_code, static_cast< sal_uInt16 >(value));
     371             :     } else {
     372          15 :         ldc(m_classFile.addIntegerInfo(value));
     373             :     }
     374       28504 : }
     375             : 
     376       10602 : void ClassFile::Code::loadStringConstant(OString const & value) {
     377       10602 :     ldc(m_classFile.addStringInfo(value));
     378       10602 : }
     379             : 
     380        1202 : void ClassFile::Code::loadLocalInteger(sal_uInt16 index) {
     381        1202 :     accessLocal(index, 0x1A, 0x15); // iload_<n>, iload
     382        1202 : }
     383             : 
     384          36 : void ClassFile::Code::loadLocalLong(sal_uInt16 index) {
     385          36 :     accessLocal(index, 0x1E, 0x16); // load_<n>, load
     386          36 : }
     387             : 
     388          19 : void ClassFile::Code::loadLocalFloat(sal_uInt16 index) {
     389          19 :     accessLocal(index, 0x22, 0x17); // load_<n>, load
     390          19 : }
     391             : 
     392         112 : void ClassFile::Code::loadLocalDouble(sal_uInt16 index) {
     393         112 :     accessLocal(index, 0x26, 0x18); // load_<n>, load
     394         112 : }
     395             : 
     396       11401 : void ClassFile::Code::loadLocalReference(sal_uInt16 index) {
     397       11401 :     accessLocal(index, 0x2A, 0x19); // aload_<n>, aload
     398       11401 : }
     399             : 
     400         364 : void ClassFile::Code::storeLocalReference(sal_uInt16 index) {
     401         364 :     accessLocal(index, 0x4B, 0x3A); // astore_<n>, astore
     402         364 : }
     403             : 
     404         416 : void ClassFile::Code::branchHere(Branch branch) {
     405         416 :     std::vector< unsigned char >::size_type n = m_code.size();
     406             :     OSL_ASSERT(n > branch && n - branch <= SAL_MAX_INT16);
     407         416 :     n -= branch;
     408         416 :     m_code[branch + 1] = static_cast< sal_uInt8 >(n >> 8);
     409         416 :     m_code[branch + 2] = static_cast< sal_uInt8 >(n & 0xFF);
     410         416 : }
     411             : 
     412         378 : void ClassFile::Code::addException(
     413             :     Position start, Position end, Position handler, OString const & type)
     414             : {
     415             :     OSL_ASSERT(start < end && end <= m_code.size() && handler <= m_code.size());
     416         378 :     if (m_exceptionTableLength == SAL_MAX_UINT16) {
     417           0 :         throw CannotDumpException("Too many exception handlers for Java class file format");
     418             :     }
     419         378 :     ++m_exceptionTableLength;
     420         378 :     appendU2(m_exceptionTable, static_cast< sal_uInt16 >(start));
     421             :         //FIXME: overflow
     422         378 :     appendU2(m_exceptionTable, static_cast< sal_uInt16 >(end));
     423             :         //FIXME: overflow
     424         378 :     appendU2(m_exceptionTable, static_cast< sal_uInt16 >(handler));
     425             :         //FIXME: overflow
     426         378 :     appendU2(m_exceptionTable, m_classFile.addClassInfo(type));
     427         378 : }
     428             : 
     429        1462 : ClassFile::Code::Position ClassFile::Code::getPosition() const {
     430        1462 :     return m_code.size();
     431             : }
     432             : 
     433        7447 : ClassFile::Code::Code(ClassFile & classFile)
     434             :     : m_classFile(classFile)
     435             :     , m_maxStack(0)
     436             :     , m_maxLocals(0)
     437        7447 :     , m_exceptionTableLength(0)
     438        7447 : {}
     439             : 
     440       10617 : void ClassFile::Code::ldc(sal_uInt16 index) {
     441       10617 :     if (index <= 0xFF) {
     442             :         // ldc <index>:
     443       10489 :         appendU1(m_code, 0x12);
     444       10489 :         appendU1(m_code, static_cast< sal_uInt8 >(index));
     445             :     } else {
     446             :         // ldc_w <indexbyte1> <indexbyte2>:
     447         128 :         appendU1(m_code, 0x13);
     448         128 :         appendU2(m_code, index);
     449             :     }
     450       10617 : }
     451             : 
     452       13134 : void ClassFile::Code::accessLocal(
     453             :     sal_uInt16 index, sal_uInt8 fastOp, sal_uInt8 normalOp)
     454             : {
     455       13134 :     if (index <= 3) {
     456             :         // ...load/store_<n>:
     457       12063 :         appendU1(m_code, static_cast< sal_uInt8 >(fastOp + index));
     458        1071 :     } else if (index <= 0xFF) {
     459             :         // ...load/store <index>:
     460        1071 :         appendU1(m_code, normalOp);
     461        1071 :         appendU1(m_code, static_cast< sal_uInt8 >(index));
     462             :     } else {
     463             :         // wide ...load/store <indexbyte1> <indexbyte2>:
     464           0 :         appendU1(m_code, 0xC4);
     465           0 :         appendU1(m_code, normalOp);
     466           0 :         appendU2(m_code, index);
     467             :     }
     468       13134 : }
     469             : 
     470        3294 : ClassFile::ClassFile(
     471             :     AccessFlags accessFlags, OString const & thisClass,
     472             :     OString const & superClass, OString const & signature):
     473             :     m_constantPoolCount(1), m_accessFlags(accessFlags), m_interfacesCount(0),
     474        3294 :     m_fieldsCount(0), m_methodsCount(0), m_attributesCount(0)
     475             : {
     476        3294 :     m_thisClass = addClassInfo(thisClass);
     477        3294 :     m_superClass = addClassInfo(superClass);
     478        3294 :     if (!signature.isEmpty()) {
     479           6 :         ++m_attributesCount;
     480           6 :         appendU2(m_attributes, addUtf8Info("Signature"));
     481           6 :         appendU4(m_attributes, 2);
     482           6 :         appendU2(m_attributes, addUtf8Info(signature));
     483             :     }
     484        3294 : }
     485             : 
     486        3294 : ClassFile::~ClassFile() {}
     487             : 
     488        7447 : ClassFile::Code * ClassFile::newCode() {
     489        7447 :     return new Code(*this);
     490             : }
     491             : 
     492        4731 : sal_uInt16 ClassFile::addIntegerInfo(sal_Int32 value) {
     493        4731 :     std::map< sal_Int32, sal_uInt16 >::iterator i(m_integerInfos.find(value));
     494        4731 :     if (i != m_integerInfos.end()) {
     495          69 :         return i->second;
     496             :     }
     497        4662 :     sal_uInt16 index = nextConstantPoolIndex(1);
     498        4662 :     appendU1(m_constantPool, 3);
     499        4662 :     appendU4(m_constantPool, static_cast< sal_uInt32 >(value));
     500        4662 :     if (!m_integerInfos.insert(
     501        9324 :             std::map< sal_Int32, sal_uInt16 >::value_type(value, index)).second)
     502             :     {
     503             :         OSL_ASSERT(false);
     504             :     }
     505        4662 :     return index;
     506             : }
     507             : 
     508          20 : sal_uInt16 ClassFile::addFloatInfo(float value) {
     509          20 :     std::map< float, sal_uInt16 >::iterator i(m_floatInfos.find(value));
     510          20 :     if (i != m_floatInfos.end()) {
     511           0 :         return i->second;
     512             :     }
     513          20 :     sal_uInt16 index = nextConstantPoolIndex(1);
     514          20 :     appendU1(m_constantPool, 4);
     515             :     union { float floatBytes; sal_uInt32 uint32Bytes; } bytes;
     516          20 :     bytes.floatBytes = value;
     517          20 :     appendU4(m_constantPool, bytes.uint32Bytes);
     518          20 :     if (!m_floatInfos.insert(
     519          40 :             std::map< float, sal_uInt16 >::value_type(value, index)).second)
     520             :     {
     521             :         OSL_ASSERT(false);
     522             :     }
     523          20 :     return index;
     524             : }
     525             : 
     526          29 : sal_uInt16 ClassFile::addLongInfo(sal_Int64 value) {
     527          29 :     std::map< sal_Int64, sal_uInt16 >::iterator i(m_longInfos.find(value));
     528          29 :     if (i != m_longInfos.end()) {
     529           0 :         return i->second;
     530             :     }
     531          29 :     sal_uInt16 index = nextConstantPoolIndex(2);
     532          29 :     appendU1(m_constantPool, 5);
     533          29 :     appendU8(m_constantPool, static_cast< sal_uInt64 >(value));
     534          29 :     if (!m_longInfos.insert(
     535          58 :             std::map< sal_Int64, sal_uInt16 >::value_type(value, index)).second)
     536             :     {
     537             :         OSL_ASSERT(false);
     538             :     }
     539          29 :     return index;
     540             : }
     541             : 
     542           0 : sal_uInt16 ClassFile::addDoubleInfo(double value) {
     543           0 :     std::map< double, sal_uInt16 >::iterator i(m_doubleInfos.find(value));
     544           0 :     if (i != m_doubleInfos.end()) {
     545           0 :         return i->second;
     546             :     }
     547           0 :     sal_uInt16 index = nextConstantPoolIndex(2);
     548           0 :     appendU1(m_constantPool, 6);
     549             :     union { double doubleBytes; sal_uInt64 uint64Bytes; } bytes;
     550           0 :     bytes.doubleBytes = value;
     551           0 :     appendU8(m_constantPool, bytes.uint64Bytes);
     552           0 :     if (!m_doubleInfos.insert(
     553           0 :             std::map< double, sal_uInt16 >::value_type(value, index)).second)
     554             :     {
     555             :         OSL_ASSERT(false);
     556             :     }
     557           0 :     return index;
     558             : }
     559             : 
     560        1951 : void ClassFile::addInterface(OString const & interface) {
     561        1951 :     if (m_interfacesCount == SAL_MAX_UINT16) {
     562           0 :         throw CannotDumpException("Too many interfaces for Java class file format");
     563             :     }
     564        1951 :     ++m_interfacesCount;
     565        1951 :     appendU2(m_interfaces, addClassInfo(interface));
     566        1951 : }
     567             : 
     568        9843 : void ClassFile::addField(
     569             :     AccessFlags accessFlags, OString const & name,
     570             :     OString const & descriptor, sal_uInt16 constantValueIndex,
     571             :     OString const & signature)
     572             : {
     573        9843 :     if (m_fieldsCount == SAL_MAX_UINT16) {
     574           0 :         throw CannotDumpException("Too many fields for Java class file format");
     575             :     }
     576        9843 :     ++m_fieldsCount;
     577        9843 :     appendU2(m_fields, static_cast< sal_uInt16 >(accessFlags));
     578        9843 :     appendU2(m_fields, addUtf8Info(name));
     579        9843 :     appendU2(m_fields, addUtf8Info(descriptor));
     580             :     appendU2(
     581             :         m_fields,
     582             :         ((constantValueIndex == 0 ? 0 : 1)
     583        9843 :          + (signature.isEmpty() ? 0 : 1)));
     584        9843 :     if (constantValueIndex != 0) {
     585        4765 :         appendU2(m_fields, addUtf8Info("ConstantValue"));
     586        4765 :         appendU4(m_fields, 2);
     587        4765 :         appendU2(m_fields, constantValueIndex);
     588             :     }
     589        9843 :     appendSignatureAttribute(m_fields, signature);
     590        9843 : }
     591             : 
     592       12722 : void ClassFile::addMethod(
     593             :     AccessFlags accessFlags, OString const & name,
     594             :     OString const & descriptor, Code const * code,
     595             :     std::vector< OString > const & exceptions,
     596             :     OString const & signature)
     597             : {
     598       12722 :     if (m_methodsCount == SAL_MAX_UINT16) {
     599           0 :         throw CannotDumpException("Too many methods for Java class file format");
     600             :     }
     601       12722 :     ++m_methodsCount;
     602       12722 :     appendU2(m_methods, static_cast< sal_uInt16 >(accessFlags));
     603       12722 :     appendU2(m_methods, addUtf8Info(name));
     604       12722 :     appendU2(m_methods, addUtf8Info(descriptor));
     605       12722 :     std::vector< OString >::size_type excs = exceptions.size();
     606       12722 :     if (excs > SAL_MAX_UINT16) {
     607           0 :         throw CannotDumpException("Too many exception specifications for Java class file format");
     608             :     }
     609             :     appendU2(
     610             :         m_methods,
     611       12722 :         ((code == 0 ? 0 : 1) + (exceptions.empty() ? 0 : 1)
     612       25444 :          + (signature.isEmpty() ? 0 : 1)));
     613       12722 :     if (code != 0) {
     614        5919 :         std::vector< unsigned char >::size_type codeSize = code->m_code.size();
     615             :         std::vector< unsigned char >::size_type exceptionTableSize
     616        5919 :             = code->m_exceptionTable.size();
     617        5919 :         if (codeSize > SAL_MAX_UINT32 - (2 + 2 + 4 + 2 + 2)
     618        5919 :             || (exceptionTableSize
     619        5919 :                 > (SAL_MAX_UINT32 - (2 + 2 + 4 + 2 + 2)
     620        5919 :                    - static_cast< sal_uInt32 >(codeSize))))
     621             :         {
     622           0 :             throw CannotDumpException("Code block is too big for Java class file format");
     623             :         }
     624        5919 :         appendU2(m_methods, addUtf8Info("Code"));
     625             :         appendU4(
     626             :             m_methods,
     627             :             (2 + 2 + 4 + static_cast< sal_uInt32 >(codeSize) + 2
     628        5919 :              + static_cast< sal_uInt32 >(exceptionTableSize) + 2));
     629        5919 :         appendU2(m_methods, code->m_maxStack);
     630        5919 :         appendU2(m_methods, code->m_maxLocals);
     631        5919 :         appendU4(m_methods, static_cast< sal_uInt32 >(codeSize));
     632        5919 :         appendStream(m_methods, code->m_code);
     633        5919 :         appendU2(m_methods, code->m_exceptionTableLength);
     634        5919 :         appendStream(m_methods, code->m_exceptionTable);
     635        5919 :         appendU2(m_methods, 0);
     636             :     }
     637       12722 :     if (!exceptions.empty()) {
     638        2068 :         appendU2(m_methods, addUtf8Info("Exceptions"));
     639             :         appendU4(
     640             :             m_methods,
     641        2068 :             static_cast< sal_uInt32 >(2 + 2 * static_cast< sal_uInt32 >(excs)));
     642        2068 :         appendU2(m_methods, static_cast< sal_uInt16 >(excs));
     643       15003 :         for (std::vector< OString >::const_iterator i(exceptions.begin());
     644       10002 :              i != exceptions.end(); ++i)
     645             :         {
     646        2933 :             appendU2(m_methods, addClassInfo(*i));
     647             :         }
     648             :     }
     649       12722 :     appendSignatureAttribute(m_methods, signature);
     650       12722 : }
     651             : 
     652        3294 : void ClassFile::write(FileStream & file) const {
     653        3294 :     writeU4(file, 0xCAFEBABE);
     654        3294 :     writeU2(file, 0);
     655        3294 :     writeU2(file, 49); // class file version of JRE 1.5
     656        3294 :     writeU2(file, m_constantPoolCount);
     657        3294 :     writeStream(file, m_constantPool);
     658        3294 :     writeU2(file, static_cast< sal_uInt16 >(m_accessFlags));
     659        3294 :     writeU2(file, m_thisClass);
     660        3294 :     writeU2(file, m_superClass);
     661        3294 :     writeU2(file, m_interfacesCount);
     662        3294 :     writeStream(file, m_interfaces);
     663        3294 :     writeU2(file, m_fieldsCount);
     664        3294 :     writeStream(file, m_fields);
     665        3294 :     writeU2(file, m_methodsCount);
     666        3294 :     writeStream(file, m_methods);
     667        3294 :     writeU2(file, m_attributesCount);
     668        3294 :     writeStream(file, m_attributes);
     669        3294 : }
     670             : 
     671      127496 : sal_uInt16 ClassFile::nextConstantPoolIndex(sal_uInt16 width) {
     672             :     OSL_ASSERT(width == 1 || width == 2);
     673      127496 :     if (m_constantPoolCount > SAL_MAX_UINT16 - width) {
     674           0 :         throw CannotDumpException("Too many constant pool items for Java class file format");
     675             :     }
     676      127496 :     sal_uInt16 index = m_constantPoolCount;
     677      127496 :     m_constantPoolCount = m_constantPoolCount + width;
     678      127496 :     return index;
     679             : }
     680             : 
     681      167302 : sal_uInt16 ClassFile::addUtf8Info(OString const & value) {
     682      167302 :     std::map< OString, sal_uInt16 >::iterator i(m_utf8Infos.find(value));
     683      167302 :     if (i != m_utf8Infos.end()) {
     684       98278 :         return i->second;
     685             :     }
     686       69024 :     if (value.getLength() > SAL_MAX_UINT16) {
     687           0 :         throw CannotDumpException("UTF-8 string too long for Java class file format");
     688             :     }
     689       69024 :     sal_uInt16 index = nextConstantPoolIndex(1);
     690       69024 :     appendU1(m_constantPool, 1);
     691       69024 :     appendU2(m_constantPool, static_cast< sal_uInt16 >(value.getLength()));
     692     1722039 :     for (sal_Int32 j = 0; j < value.getLength(); ++j) {
     693     1653015 :         appendU1(m_constantPool, static_cast< sal_uInt8 >(value[j]));
     694             :     }
     695       69024 :     if (!m_utf8Infos.insert(
     696      138048 :             std::map< OString, sal_uInt16 >::value_type(value, index)).
     697       69024 :         second)
     698             :     {
     699             :         OSL_ASSERT(false);
     700             :     }
     701       69024 :     return index;
     702             : }
     703             : 
     704       50044 : sal_uInt16 ClassFile::addClassInfo(OString const & type) {
     705       50044 :     sal_uInt16 nameIndex = addUtf8Info(type);
     706             :     std::map< sal_uInt16, sal_uInt16 >::iterator i(
     707       50044 :         m_classInfos.find(nameIndex));
     708       50044 :     if (i != m_classInfos.end()) {
     709       32194 :         return i->second;
     710             :     }
     711       17850 :     sal_uInt16 index = nextConstantPoolIndex(1);
     712       17850 :     appendU1(m_constantPool, 7);
     713       17850 :     appendU2(m_constantPool, nameIndex);
     714       17850 :     if (!m_classInfos.insert(
     715       35700 :             std::map< sal_uInt16, sal_uInt16 >::value_type(nameIndex, index)).
     716       17850 :         second)
     717             :     {
     718             :         OSL_ASSERT(false);
     719             :     }
     720       17850 :     return index;
     721             : }
     722             : 
     723       10602 : sal_uInt16 ClassFile::addStringInfo(OString const & value) {
     724       10602 :     sal_uInt16 stringIndex = addUtf8Info(value);
     725             :     std::map< sal_uInt16, sal_uInt16 >::iterator i(
     726       10602 :         m_stringInfos.find(stringIndex));
     727       10602 :     if (i != m_stringInfos.end()) {
     728         783 :         return i->second;
     729             :     }
     730        9819 :     sal_uInt16 index = nextConstantPoolIndex(1);
     731        9819 :     appendU1(m_constantPool, 8);
     732        9819 :     appendU2(m_constantPool, stringIndex);
     733        9819 :     if (!m_stringInfos.insert(
     734       19638 :             std::map< sal_uInt16, sal_uInt16 >::value_type(stringIndex, index)).
     735        9819 :         second)
     736             :     {
     737             :         OSL_ASSERT(false);
     738             :     }
     739        9819 :     return index;
     740             : }
     741             : 
     742        8507 : sal_uInt16 ClassFile::addFieldrefInfo(
     743             :     OString const & type, OString const & name,
     744             :     OString const & descriptor)
     745             : {
     746        8507 :     sal_uInt16 classIndex = addClassInfo(type);
     747        8507 :     sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
     748        8507 :     sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
     749        8507 :         | nameAndTypeIndex;
     750        8507 :     std::map< sal_uInt32, sal_uInt16 >::iterator i(m_fieldrefInfos.find(key));
     751        8507 :     if (i != m_fieldrefInfos.end()) {
     752        2919 :         return i->second;
     753             :     }
     754        5588 :     sal_uInt16 index = nextConstantPoolIndex(1);
     755        5588 :     appendU1(m_constantPool, 9);
     756        5588 :     appendU2(m_constantPool, classIndex);
     757        5588 :     appendU2(m_constantPool, nameAndTypeIndex);
     758        5588 :     if (!m_fieldrefInfos.insert(
     759       11176 :             std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
     760             :     {
     761             :         OSL_ASSERT(false);
     762             :     }
     763        5588 :     return index;
     764             : }
     765             : 
     766       15059 : sal_uInt16 ClassFile::addMethodrefInfo(
     767             :     OString const & type, OString const & name,
     768             :     OString const & descriptor)
     769             : {
     770       15059 :     sal_uInt16 classIndex = addClassInfo(type);
     771       15059 :     sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
     772       15059 :     sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
     773       15059 :         | nameAndTypeIndex;
     774       15059 :     std::map< sal_uInt32, sal_uInt16 >::iterator i(m_methodrefInfos.find(key));
     775       15059 :     if (i != m_methodrefInfos.end()) {
     776        8116 :         return i->second;
     777             :     }
     778        6943 :     sal_uInt16 index = nextConstantPoolIndex(1);
     779        6943 :     appendU1(m_constantPool, 10);
     780        6943 :     appendU2(m_constantPool, classIndex);
     781        6943 :     appendU2(m_constantPool, nameAndTypeIndex);
     782        6943 :     if (!m_methodrefInfos.insert(
     783       13886 :             std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
     784             :     {
     785             :         OSL_ASSERT(false);
     786             :     }
     787        6943 :     return index;
     788             : }
     789             : 
     790         765 : sal_uInt16 ClassFile::addInterfaceMethodrefInfo(
     791             :     OString const & type, OString const & name,
     792             :     OString const & descriptor)
     793             : {
     794         765 :     sal_uInt16 classIndex = addClassInfo(type);
     795         765 :     sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
     796         765 :     sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
     797         765 :         | nameAndTypeIndex;
     798             :     std::map< sal_uInt32, sal_uInt16 >::iterator i(
     799         765 :         m_interfaceMethodrefInfos.find(key));
     800         765 :     if (i != m_interfaceMethodrefInfos.end()) {
     801          88 :         return i->second;
     802             :     }
     803         677 :     sal_uInt16 index = nextConstantPoolIndex(1);
     804         677 :     appendU1(m_constantPool, 11);
     805         677 :     appendU2(m_constantPool, classIndex);
     806         677 :     appendU2(m_constantPool, nameAndTypeIndex);
     807         677 :     if (!m_interfaceMethodrefInfos.insert(
     808        1354 :             std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
     809             :     {
     810             :         OSL_ASSERT(false);
     811             :     }
     812         677 :     return index;
     813             : }
     814             : 
     815       24331 : sal_uInt16 ClassFile::addNameAndTypeInfo(
     816             :     OString const & name, OString const & descriptor)
     817             : {
     818       24331 :     sal_uInt16 nameIndex = addUtf8Info(name);
     819       24331 :     sal_uInt16 descriptorIndex = addUtf8Info(descriptor);
     820       24331 :     sal_uInt32 key = (static_cast< sal_uInt32 >(nameIndex) << 16)
     821       24331 :         | descriptorIndex;
     822             :     std::map< sal_uInt32, sal_uInt16 >::iterator i(
     823       24331 :         m_nameAndTypeInfos.find(key));
     824       24331 :     if (i != m_nameAndTypeInfos.end()) {
     825       11447 :         return i->second;
     826             :     }
     827       12884 :     sal_uInt16 index = nextConstantPoolIndex(1);
     828       12884 :     appendU1(m_constantPool, 12);
     829       12884 :     appendU2(m_constantPool, nameIndex);
     830       12884 :     appendU2(m_constantPool, descriptorIndex);
     831       12884 :     if (!m_nameAndTypeInfos.insert(
     832       25768 :             std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
     833             :     {
     834             :         OSL_ASSERT(false);
     835             :     }
     836       12884 :     return index;
     837             : }
     838             : 
     839       22565 : void ClassFile::appendSignatureAttribute(
     840             :     std::vector< unsigned char > & stream, OString const & signature)
     841             : {
     842       22565 :     if (!signature.isEmpty()) {
     843          50 :         appendU2(stream, addUtf8Info("Signature"));
     844          50 :         appendU4(stream, 2);
     845          50 :         appendU2(stream, addUtf8Info(signature));
     846             :     }
     847       22565 : }
     848             : 
     849             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11