update dev300-m58
[ooovba.git] / codemaker / source / javamaker / classfile.cxx
blob035e9d9bab883fe617b1fa60f340c6e5c01afe49
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: classfile.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_codemaker.hxx"
34 #include "classfile.hxx"
36 #include "codemaker/global.hxx"
37 #include "codemaker/options.hxx"
38 #include "codemaker/unotype.hxx"
40 #include "boost/static_assert.hpp"
41 #include "osl/diagnose.h"
42 #include "rtl/string.h"
43 #include "rtl/string.hxx"
44 #include "sal/types.h"
46 #include <map>
47 #include <utility>
48 #include <vector>
50 using codemaker::javamaker::ClassFile;
52 namespace {
54 void appendU1(std::vector< unsigned char > & stream, sal_uInt8 data) {
55 stream.push_back(static_cast< unsigned char >(data));
58 void appendU2(std::vector< unsigned char > & stream, sal_uInt16 data) {
59 stream.push_back(static_cast< unsigned char >(data >> 8));
60 stream.push_back(static_cast< unsigned char >(data & 0xFF));
63 void appendU4(std::vector< unsigned char > & stream, sal_uInt32 data) {
64 stream.push_back(static_cast< unsigned char >(data >> 24));
65 stream.push_back(static_cast< unsigned char >((data >> 16) & 0xFF));
66 stream.push_back(static_cast< unsigned char >((data >> 8) & 0xFF));
67 stream.push_back(static_cast< unsigned char >(data & 0xFF));
70 void appendU8(std::vector< unsigned char > & stream, sal_uInt64 data) {
71 stream.push_back(static_cast< unsigned char >(data >> 56));
72 stream.push_back(static_cast< unsigned char >((data >> 48) & 0xFF));
73 stream.push_back(static_cast< unsigned char >((data >> 40) & 0xFF));
74 stream.push_back(static_cast< unsigned char >((data >> 32) & 0xFF));
75 stream.push_back(static_cast< unsigned char >((data >> 24) & 0xFF));
76 stream.push_back(static_cast< unsigned char >((data >> 16) & 0xFF));
77 stream.push_back(static_cast< unsigned char >((data >> 8) & 0xFF));
78 stream.push_back(static_cast< unsigned char >(data & 0xFF));
81 void appendStream(
82 std::vector< unsigned char > & stream,
83 std::vector< unsigned char > const & data)
85 stream.insert(stream.end(), data.begin(), data.end());
88 void write(FileStream & file, void const * buffer, sal_uInt64 size) {
89 if (!file.write(buffer, size)) {
90 throw CannotDumpException(
91 rtl::OString(RTL_CONSTASCII_STRINGPARAM("Error writing file")));
95 void writeU1(FileStream & file, sal_uInt8 data) {
96 unsigned char buf[] = { static_cast< unsigned char >(data) };
97 write(file, &buf, sizeof buf);
100 void writeU2(FileStream & file, sal_uInt16 data) {
101 unsigned char buf[] = {
102 static_cast< unsigned char >(data >> 8),
103 static_cast< unsigned char >(data & 0xFF) };
104 write(file, buf, sizeof buf);
107 void writeU4(FileStream & file, sal_uInt32 data) {
108 unsigned char buf[] = {
109 static_cast< unsigned char >(data >> 24),
110 static_cast< unsigned char >((data >> 16) & 0xFF),
111 static_cast< unsigned char >((data >> 8) & 0xFF),
112 static_cast< unsigned char >(data & 0xFF) };
113 write(file, buf, sizeof buf);
116 void writeStream(FileStream & file, std::vector< unsigned char > const & stream)
118 std::vector< unsigned char >::size_type n = stream.size();
119 BOOST_STATIC_ASSERT(
120 sizeof (std::vector< unsigned char >::size_type)
121 <= sizeof (sal_uInt64));
122 // both unsigned integral, so sizeof is a practically sufficient
123 // approximation of std::numeric_limits<T1>::max() <=
124 // std::numeric_limits<T2>::max()
125 if (n != 0) {
126 write(file, &stream[0], static_cast< sal_uInt64 >(n));
132 ClassFile::Code::~Code() {}
134 void ClassFile::Code::instrAastore() {
135 // aastore:
136 appendU1(m_code, 0x53);
139 void ClassFile::Code::instrAconstNull() {
140 // aconst_null:
141 appendU1(m_code, 0x01);
144 void ClassFile::Code::instrAnewarray(rtl::OString const & type) {
145 // anewarray <indexbyte1> <indexbyte2>:
146 appendU1(m_code, 0xBD);
147 appendU2(m_code, m_classFile.addClassInfo(type));
150 void ClassFile::Code::instrAreturn() {
151 // areturn:
152 appendU1(m_code, 0xB0);
155 void ClassFile::Code::instrAthrow() {
156 // athrow:
157 appendU1(m_code, 0xBF);
160 void ClassFile::Code::instrCheckcast(rtl::OString const & type) {
161 // checkcast <indexbyte1> <indexbyte2>:
162 appendU1(m_code, 0xC0);
163 appendU2(m_code, m_classFile.addClassInfo(type));
166 void ClassFile::Code::instrDup() {
167 // dup:
168 appendU1(m_code, 0x59);
171 void ClassFile::Code::instrGetstatic(
172 rtl::OString const & type, rtl::OString const & name,
173 rtl::OString const & descriptor)
175 // getstatic <indexbyte1> <indexbyte2>:
176 appendU1(m_code, 0xB2);
177 appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
180 ClassFile::Code::Branch ClassFile::Code::instrIfAcmpne() {
181 // if_acmpne <branchbyte1> <branchbyte2>:
182 Branch branch = m_code.size();
183 appendU1(m_code, 0xA6);
184 appendU2(m_code, 0);
185 return branch;
188 ClassFile::Code::Branch ClassFile::Code::instrIfeq() {
189 // ifeq <branchbyte1> <branchbyte2>:
190 Branch branch = m_code.size();
191 appendU1(m_code, 0x99);
192 appendU2(m_code, 0);
193 return branch;
196 ClassFile::Code::Branch ClassFile::Code::instrIfnull() {
197 // ifnull <branchbyte1> <branchbyte2>:
198 Branch branch = m_code.size();
199 appendU1(m_code, 0xC6);
200 appendU2(m_code, 0);
201 return branch;
204 void ClassFile::Code::instrInstanceof(rtl::OString const & type) {
205 // instanceof <indexbyte1> <indexbyte2>:
206 appendU1(m_code, 0xC1);
207 appendU2(m_code, m_classFile.addClassInfo(type));
210 void ClassFile::Code::instrInvokeinterface(
211 rtl::OString const & type, rtl::OString const & name,
212 rtl::OString const & descriptor, sal_uInt8 args)
214 // invokeinterface <indexbyte1> <indexbyte2> <nargs> 0:
215 appendU1(m_code, 0xB9);
216 appendU2(
217 m_code, m_classFile.addInterfaceMethodrefInfo(type, name, descriptor));
218 appendU1(m_code, args);
219 appendU1(m_code, 0);
222 void ClassFile::Code::instrInvokespecial(
223 rtl::OString const & type, rtl::OString const & name,
224 rtl::OString const & descriptor)
226 // invokespecial <indexbyte1> <indexbyte2>:
227 appendU1(m_code, 0xB7);
228 appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
231 void ClassFile::Code::instrInvokestatic(
232 rtl::OString const & type, rtl::OString const & name,
233 rtl::OString const & descriptor)
235 // invokestatic <indexbyte1> <indexbyte2>:
236 appendU1(m_code, 0xB8);
237 appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
240 void ClassFile::Code::instrInvokevirtual(
241 rtl::OString const & type, rtl::OString const & name,
242 rtl::OString const & descriptor)
244 // invokevirtual <indexbyte1> <indexbyte2>:
245 appendU1(m_code, 0xB6);
246 appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
249 void ClassFile::Code::instrLookupswitch(
250 Code const * defaultBlock,
251 std::list< std::pair< sal_Int32, Code * > > const & blocks)
253 // lookupswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
254 // <defaultbyte4> <npairs1> <npairs2> <npairs3> <npairs4>
255 // <match--offset pairs...>:
256 std::list< std::pair< sal_Int32, Code * > >::size_type size = blocks.size();
257 if (size > SAL_MAX_INT32) {
258 throw CannotDumpException(
259 rtl::OString(
260 RTL_CONSTASCII_STRINGPARAM(
261 "Lookup-switch too large for Java class file format")));
263 Position pos1 = m_code.size();
264 appendU1(m_code, 0xAB);
265 int pad = (pos1 + 1) % 4;
266 {for (int i = 0; i < pad; ++i) {
267 appendU1(m_code, 0);
269 Position pos2 = pos1 + 1 + pad + 8 + blocks.size() * 8; //FIXME: overflow
270 appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1)); //FIXME: overflow
271 pos2 += defaultBlock->m_code.size(); //FIXME: overflow
272 appendU4(m_code, static_cast< sal_uInt32 >(size));
273 {for (std::list< std::pair< sal_Int32, Code * > >::const_iterator i(
274 blocks.begin());
275 i != blocks.end(); ++i)
277 appendU4(m_code, static_cast< sal_uInt32 >(i->first));
278 appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1));
279 //FIXME: overflow
280 pos2 += i->second->m_code.size(); //FIXME: overflow
282 appendStream(m_code, defaultBlock->m_code);
283 {for (std::list< std::pair< sal_Int32, Code * > >::const_iterator i(
284 blocks.begin());
285 i != blocks.end(); ++i)
287 appendStream(m_code, i->second->m_code);
291 void ClassFile::Code::instrNew(rtl::OString const & type) {
292 // new <indexbyte1> <indexbyte2>:
293 appendU1(m_code, 0xBB);
294 appendU2(m_code, m_classFile.addClassInfo(type));
297 void ClassFile::Code::instrNewarray(codemaker::UnoType::Sort sort) {
298 OSL_ASSERT(
299 sort >= codemaker::UnoType::SORT_BOOLEAN
300 && sort <= codemaker::UnoType::SORT_CHAR);
301 // newarray <atype>:
302 appendU1(m_code, 0xBC);
303 static sal_uInt8 const atypes[codemaker::UnoType::SORT_CHAR] = {
304 0x04, 0x08, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x06, 0x07, 0x05 };
305 appendU1(m_code, atypes[sort - 1]);
308 void ClassFile::Code::instrPop() {
309 // pop:
310 appendU1(m_code, 0x57);
313 void ClassFile::Code::instrPutfield(
314 rtl::OString const & type, rtl::OString const & name,
315 rtl::OString const & descriptor)
317 // putfield <indexbyte1> <indexbyte2>:
318 appendU1(m_code, 0xB5);
319 appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
322 void ClassFile::Code::instrPutstatic(
323 rtl::OString const & type, rtl::OString const & name,
324 rtl::OString const & descriptor)
326 // putstatic <indexbyte1> <indexbyte2>:
327 appendU1(m_code, 0xB3);
328 appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
331 void ClassFile::Code::instrReturn() {
332 // return:
333 appendU1(m_code, 0xB1);
336 void ClassFile::Code::instrSwap() {
337 // swap:
338 appendU1(m_code, 0x5F);
341 void ClassFile::Code::instrTableswitch(
342 Code const * defaultBlock, sal_Int32 low,
343 std::list< Code * > const & blocks)
345 // tableswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
346 // <defaultbyte4> <lowbyte1> <lowbyte2> <lowbyte3> <lowbyte4> <highbyte1>
347 // <highbyte2> <highbyte3> <highbyte4> <jump offsets...>:
348 Position pos1 = m_code.size();
349 appendU1(m_code, 0xAA);
350 int pad = (pos1 + 1) % 4;
351 {for (int i = 0; i < pad; ++i) {
352 appendU1(m_code, 0);
354 std::list< Code * >::size_type size = blocks.size();
355 Position pos2 = pos1 + 1 + pad + 12 + size * 4; //FIXME: overflow
356 sal_uInt32 defaultOffset = static_cast< sal_uInt32 >(pos2 - pos1);
357 //FIXME: overflow
358 appendU4(m_code, defaultOffset);
359 pos2 += defaultBlock->m_code.size(); //FIXME: overflow
360 appendU4(m_code, static_cast< sal_uInt32 >(low));
361 appendU4(m_code, static_cast< sal_uInt32 >(low + (size - 1)));
362 {for (std::list< Code * >::const_iterator i(blocks.begin());
363 i != blocks.end(); ++i)
365 if (*i == 0) {
366 appendU4(m_code, defaultOffset);
367 } else {
368 appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1));
369 //FIXME: overflow
370 pos2 += (*i)->m_code.size(); //FIXME: overflow
373 appendStream(m_code, defaultBlock->m_code);
374 {for (std::list< Code * >::const_iterator i(blocks.begin());
375 i != blocks.end(); ++i)
377 if (*i != 0) {
378 appendStream(m_code, (*i)->m_code);
383 void ClassFile::Code::loadIntegerConstant(sal_Int32 value) {
384 if (value >= -1 && value <= 5) {
385 // iconst_<i>:
386 appendU1(m_code, static_cast< sal_uInt8 >(0x02 + value + 1));
387 } else if (value >= -128 && value <= 127) {
388 // bipush <byte>:
389 appendU1(m_code, 0x10);
390 appendU1(m_code, static_cast< sal_uInt8 >(value));
391 } else if (value >= -32768 && value <= 32767) {
392 // sipush <byte1> <byte2>:
393 appendU1(m_code, 0x11);
394 appendU2(m_code, static_cast< sal_uInt16 >(value));
395 } else {
396 ldc(m_classFile.addIntegerInfo(value));
400 void ClassFile::Code::loadStringConstant(rtl::OString const & value) {
401 ldc(m_classFile.addStringInfo(value));
404 void ClassFile::Code::loadLocalInteger(sal_uInt16 index) {
405 accessLocal(index, 0x1A, 0x15); // iload_<n>, iload
408 void ClassFile::Code::loadLocalLong(sal_uInt16 index) {
409 accessLocal(index, 0x1E, 0x16); // load_<n>, load
412 void ClassFile::Code::loadLocalFloat(sal_uInt16 index) {
413 accessLocal(index, 0x22, 0x17); // load_<n>, load
416 void ClassFile::Code::loadLocalDouble(sal_uInt16 index) {
417 accessLocal(index, 0x26, 0x18); // load_<n>, load
420 void ClassFile::Code::loadLocalReference(sal_uInt16 index) {
421 accessLocal(index, 0x2A, 0x19); // aload_<n>, aload
424 void ClassFile::Code::storeLocalReference(sal_uInt16 index) {
425 accessLocal(index, 0x4B, 0x3A); // astore_<n>, astore
428 void ClassFile::Code::branchHere(Branch branch) {
429 std::vector< unsigned char >::size_type n = m_code.size();
430 OSL_ASSERT(n > branch && n - branch <= SAL_MAX_INT16);
431 n -= branch;
432 m_code[branch + 1] = static_cast< sal_uInt8 >(n >> 8);
433 m_code[branch + 2] = static_cast< sal_uInt8 >(n & 0xFF);
436 void ClassFile::Code::addException(
437 Position start, Position end, Position handler, rtl::OString const & type)
439 OSL_ASSERT(start < end && end <= m_code.size() && handler <= m_code.size());
440 if (m_exceptionTableLength == SAL_MAX_UINT16) {
441 throw CannotDumpException(
442 rtl::OString(
443 RTL_CONSTASCII_STRINGPARAM(
444 "Too many exception handlers for Java class file format")));
446 ++m_exceptionTableLength;
447 appendU2(m_exceptionTable, static_cast< sal_uInt16 >(start));
448 //FIXME: overflow
449 appendU2(m_exceptionTable, static_cast< sal_uInt16 >(end));
450 //FIXME: overflow
451 appendU2(m_exceptionTable, static_cast< sal_uInt16 >(handler));
452 //FIXME: overflow
453 appendU2(m_exceptionTable, m_classFile.addClassInfo(type));
456 ClassFile::Code::Position ClassFile::Code::getPosition() const {
457 return m_code.size();
460 ClassFile::Code::Code(ClassFile & classFile):
461 m_classFile(classFile), m_exceptionTableLength(0)
464 void ClassFile::Code::ldc(sal_uInt16 index) {
465 if (index <= 0xFF) {
466 // ldc <index>:
467 appendU1(m_code, 0x12);
468 appendU1(m_code, static_cast< sal_uInt8 >(index));
469 } else {
470 // ldc_w <indexbyte1> <indexbyte2>:
471 appendU1(m_code, 0x13);
472 appendU2(m_code, index);
476 void ClassFile::Code::accessLocal(
477 sal_uInt16 index, sal_uInt8 fastOp, sal_uInt8 normalOp)
479 if (index <= 3) {
480 // ...load/store_<n>:
481 appendU1(m_code, static_cast< sal_uInt8 >(fastOp + index));
482 } else if (index <= 0xFF) {
483 // ...load/store <index>:
484 appendU1(m_code, normalOp);
485 appendU1(m_code, static_cast< sal_uInt8 >(index));
486 } else {
487 // wide ...load/store <indexbyte1> <indexbyte2>:
488 appendU1(m_code, 0xC4);
489 appendU1(m_code, normalOp);
490 appendU2(m_code, index);
494 ClassFile::ClassFile(
495 AccessFlags accessFlags, rtl::OString const & thisClass,
496 rtl::OString const & superClass, rtl::OString const & signature):
497 m_constantPoolCount(1), m_accessFlags(accessFlags), m_interfacesCount(0),
498 m_fieldsCount(0), m_methodsCount(0), m_attributesCount(0)
500 m_thisClass = addClassInfo(thisClass);
501 m_superClass = addClassInfo(superClass);
502 if (signature.getLength() != 0) {
503 ++m_attributesCount;
504 appendU2(
505 m_attributes,
506 addUtf8Info(rtl::OString(RTL_CONSTASCII_STRINGPARAM("Signature"))));
507 appendU4(m_attributes, 2);
508 appendU2(m_attributes, addUtf8Info(signature));
512 ClassFile::~ClassFile() {}
514 ClassFile::Code * ClassFile::newCode() {
515 return new Code(*this);
518 sal_uInt16 ClassFile::addIntegerInfo(sal_Int32 value) {
519 std::map< sal_Int32, sal_uInt16 >::iterator i(m_integerInfos.find(value));
520 if (i != m_integerInfos.end()) {
521 return i->second;
523 sal_uInt16 index = nextConstantPoolIndex(1);
524 appendU1(m_constantPool, 3);
525 appendU4(m_constantPool, static_cast< sal_uInt32 >(value));
526 if (!m_integerInfos.insert(
527 std::map< sal_Int32, sal_uInt16 >::value_type(value, index)).second)
529 OSL_ASSERT(false);
531 return index;
534 sal_uInt16 ClassFile::addFloatInfo(float value) {
535 std::map< float, sal_uInt16 >::iterator i(m_floatInfos.find(value));
536 if (i != m_floatInfos.end()) {
537 return i->second;
539 sal_uInt16 index = nextConstantPoolIndex(1);
540 appendU1(m_constantPool, 4);
541 union { float floatBytes; sal_uInt32 uint32Bytes; } bytes;
542 bytes.floatBytes = value;
543 appendU4(m_constantPool, bytes.uint32Bytes);
544 if (!m_floatInfos.insert(
545 std::map< float, sal_uInt16 >::value_type(value, index)).second)
547 OSL_ASSERT(false);
549 return index;
552 sal_uInt16 ClassFile::addLongInfo(sal_Int64 value) {
553 std::map< sal_Int64, sal_uInt16 >::iterator i(m_longInfos.find(value));
554 if (i != m_longInfos.end()) {
555 return i->second;
557 sal_uInt16 index = nextConstantPoolIndex(2);
558 appendU1(m_constantPool, 5);
559 appendU8(m_constantPool, static_cast< sal_uInt64 >(value));
560 if (!m_longInfos.insert(
561 std::map< sal_Int64, sal_uInt16 >::value_type(value, index)).second)
563 OSL_ASSERT(false);
565 return index;
568 sal_uInt16 ClassFile::addDoubleInfo(double value) {
569 std::map< double, sal_uInt16 >::iterator i(m_doubleInfos.find(value));
570 if (i != m_doubleInfos.end()) {
571 return i->second;
573 sal_uInt16 index = nextConstantPoolIndex(2);
574 appendU1(m_constantPool, 6);
575 union { double doubleBytes; sal_uInt64 uint64Bytes; } bytes;
576 bytes.doubleBytes = value;
577 appendU8(m_constantPool, bytes.uint64Bytes);
578 if (!m_doubleInfos.insert(
579 std::map< double, sal_uInt16 >::value_type(value, index)).second)
581 OSL_ASSERT(false);
583 return index;
586 void ClassFile::addInterface(rtl::OString const & interface) {
587 if (m_interfacesCount == SAL_MAX_UINT16) {
588 throw CannotDumpException(
589 rtl::OString(
590 RTL_CONSTASCII_STRINGPARAM(
591 "Too many interfaces for Java class file format")));
593 ++m_interfacesCount;
594 appendU2(m_interfaces, addClassInfo(interface));
597 void ClassFile::addField(
598 AccessFlags accessFlags, rtl::OString const & name,
599 rtl::OString const & descriptor, sal_uInt16 constantValueIndex,
600 rtl::OString const & signature)
602 if (m_fieldsCount == SAL_MAX_UINT16) {
603 throw CannotDumpException(
604 rtl::OString(
605 RTL_CONSTASCII_STRINGPARAM(
606 "Too many fields for Java class file format")));
608 ++m_fieldsCount;
609 appendU2(m_fields, static_cast< sal_uInt16 >(accessFlags));
610 appendU2(m_fields, addUtf8Info(name));
611 appendU2(m_fields, addUtf8Info(descriptor));
612 appendU2(
613 m_fields,
614 ((constantValueIndex == 0 ? 0 : 1)
615 + (signature.getLength() == 0 ? 0 : 1)));
616 if (constantValueIndex != 0) {
617 appendU2(
618 m_fields,
619 addUtf8Info(
620 rtl::OString(RTL_CONSTASCII_STRINGPARAM("ConstantValue"))));
621 appendU4(m_fields, 2);
622 appendU2(m_fields, constantValueIndex);
624 appendSignatureAttribute(m_fields, signature);
627 void ClassFile::addMethod(
628 AccessFlags accessFlags, rtl::OString const & name,
629 rtl::OString const & descriptor, Code const * code,
630 std::vector< rtl::OString > const & exceptions,
631 rtl::OString const & signature)
633 if (m_methodsCount == SAL_MAX_UINT16) {
634 throw CannotDumpException(
635 rtl::OString(
636 RTL_CONSTASCII_STRINGPARAM(
637 "Too many methods for Java class file format")));
639 ++m_methodsCount;
640 appendU2(m_methods, static_cast< sal_uInt16 >(accessFlags));
641 appendU2(m_methods, addUtf8Info(name));
642 appendU2(m_methods, addUtf8Info(descriptor));
643 std::vector< rtl::OString >::size_type excs = exceptions.size();
644 if (excs > SAL_MAX_UINT16) {
645 throw CannotDumpException(
646 rtl::OString(
647 RTL_CONSTASCII_STRINGPARAM(
648 "Too many exception specifications for Java class file"
649 " format")));
651 appendU2(
652 m_methods,
653 ((code == 0 ? 0 : 1) + (exceptions.empty() ? 0 : 1)
654 + (signature.getLength() == 0 ? 0 : 1)));
655 if (code != 0) {
656 std::vector< unsigned char >::size_type codeSize = code->m_code.size();
657 std::vector< unsigned char >::size_type exceptionTableSize
658 = code->m_exceptionTable.size();
659 if (codeSize > SAL_MAX_UINT32 - (2 + 2 + 4 + 2 + 2)
660 || (exceptionTableSize
661 > (SAL_MAX_UINT32 - (2 + 2 + 4 + 2 + 2)
662 - static_cast< sal_uInt32 >(codeSize))))
664 throw CannotDumpException(
665 rtl::OString(
666 RTL_CONSTASCII_STRINGPARAM(
667 "Code block is too big for Java class file format")));
669 appendU2(
670 m_methods,
671 addUtf8Info(rtl::OString(RTL_CONSTASCII_STRINGPARAM("Code"))));
672 appendU4(
673 m_methods,
674 (2 + 2 + 4 + static_cast< sal_uInt32 >(codeSize) + 2
675 + static_cast< sal_uInt32 >(exceptionTableSize) + 2));
676 appendU2(m_methods, code->m_maxStack);
677 appendU2(m_methods, code->m_maxLocals);
678 appendU4(m_methods, static_cast< sal_uInt32 >(codeSize));
679 appendStream(m_methods, code->m_code);
680 appendU2(m_methods, code->m_exceptionTableLength);
681 appendStream(m_methods, code->m_exceptionTable);
682 appendU2(m_methods, 0);
684 if (!exceptions.empty()) {
685 appendU2(
686 m_methods,
687 addUtf8Info(
688 rtl::OString(RTL_CONSTASCII_STRINGPARAM("Exceptions"))));
689 appendU4(
690 m_methods,
691 static_cast< sal_uInt32 >(2 + 2 * static_cast< sal_uInt32 >(excs)));
692 appendU2(m_methods, static_cast< sal_uInt16 >(excs));
693 for (std::vector< rtl::OString >::const_iterator i(exceptions.begin());
694 i != exceptions.end(); ++i)
696 appendU2(m_methods, addClassInfo(*i));
699 appendSignatureAttribute(m_methods, signature);
702 void ClassFile::write(FileStream & file) const {
703 writeU4(file, 0xCAFEBABE);
704 writeU2(file, 0);
705 writeU2(file, 46);
706 writeU2(file, m_constantPoolCount);
707 writeStream(file, m_constantPool);
708 writeU2(file, static_cast< sal_uInt16 >(m_accessFlags));
709 writeU2(file, m_thisClass);
710 writeU2(file, m_superClass);
711 writeU2(file, m_interfacesCount);
712 writeStream(file, m_interfaces);
713 writeU2(file, m_fieldsCount);
714 writeStream(file, m_fields);
715 writeU2(file, m_methodsCount);
716 writeStream(file, m_methods);
717 writeU2(file, m_attributesCount);
718 writeStream(file, m_attributes);
721 sal_uInt16 ClassFile::nextConstantPoolIndex(sal_uInt16 width) {
722 OSL_ASSERT(width == 1 || width == 2);
723 if (m_constantPoolCount > SAL_MAX_UINT16 - width) {
724 throw CannotDumpException(
725 rtl::OString(
726 RTL_CONSTASCII_STRINGPARAM(
727 "Too many constant pool items for Java class file"
728 " format")));
730 sal_uInt16 index = m_constantPoolCount;
731 m_constantPoolCount = m_constantPoolCount + width;
732 return index;
735 sal_uInt16 ClassFile::addUtf8Info(rtl::OString const & value) {
736 std::map< rtl::OString, sal_uInt16 >::iterator i(m_utf8Infos.find(value));
737 if (i != m_utf8Infos.end()) {
738 return i->second;
740 if (value.getLength() > SAL_MAX_UINT16) {
741 throw CannotDumpException(
742 rtl::OString(
743 RTL_CONSTASCII_STRINGPARAM(
744 "UTF-8 string too long for Java class file format")));
746 sal_uInt16 index = nextConstantPoolIndex(1);
747 appendU1(m_constantPool, 1);
748 appendU2(m_constantPool, static_cast< sal_uInt16 >(value.getLength()));
749 for (sal_Int32 j = 0; j < value.getLength(); ++j) {
750 appendU1(m_constantPool, static_cast< sal_uInt8 >(value[j]));
752 if (!m_utf8Infos.insert(
753 std::map< rtl::OString, sal_uInt16 >::value_type(value, index)).
754 second)
756 OSL_ASSERT(false);
758 return index;
761 sal_uInt16 ClassFile::addClassInfo(rtl::OString const & type) {
762 sal_uInt16 nameIndex = addUtf8Info(type);
763 std::map< sal_uInt16, sal_uInt16 >::iterator i(
764 m_classInfos.find(nameIndex));
765 if (i != m_classInfos.end()) {
766 return i->second;
768 sal_uInt16 index = nextConstantPoolIndex(1);
769 appendU1(m_constantPool, 7);
770 appendU2(m_constantPool, nameIndex);
771 if (!m_classInfos.insert(
772 std::map< sal_uInt16, sal_uInt16 >::value_type(nameIndex, index)).
773 second)
775 OSL_ASSERT(false);
777 return index;
780 sal_uInt16 ClassFile::addStringInfo(rtl::OString const & value) {
781 sal_uInt16 stringIndex = addUtf8Info(value);
782 std::map< sal_uInt16, sal_uInt16 >::iterator i(
783 m_stringInfos.find(stringIndex));
784 if (i != m_stringInfos.end()) {
785 return i->second;
787 sal_uInt16 index = nextConstantPoolIndex(1);
788 appendU1(m_constantPool, 8);
789 appendU2(m_constantPool, stringIndex);
790 if (!m_stringInfos.insert(
791 std::map< sal_uInt16, sal_uInt16 >::value_type(stringIndex, index)).
792 second)
794 OSL_ASSERT(false);
796 return index;
799 sal_uInt16 ClassFile::addFieldrefInfo(
800 rtl::OString const & type, rtl::OString const & name,
801 rtl::OString const & descriptor)
803 sal_uInt16 classIndex = addClassInfo(type);
804 sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
805 sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
806 | nameAndTypeIndex;
807 std::map< sal_uInt32, sal_uInt16 >::iterator i(m_fieldrefInfos.find(key));
808 if (i != m_fieldrefInfos.end()) {
809 return i->second;
811 sal_uInt16 index = nextConstantPoolIndex(1);
812 appendU1(m_constantPool, 9);
813 appendU2(m_constantPool, classIndex);
814 appendU2(m_constantPool, nameAndTypeIndex);
815 if (!m_fieldrefInfos.insert(
816 std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
818 OSL_ASSERT(false);
820 return index;
823 sal_uInt16 ClassFile::addMethodrefInfo(
824 rtl::OString const & type, rtl::OString const & name,
825 rtl::OString const & descriptor)
827 sal_uInt16 classIndex = addClassInfo(type);
828 sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
829 sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
830 | nameAndTypeIndex;
831 std::map< sal_uInt32, sal_uInt16 >::iterator i(m_methodrefInfos.find(key));
832 if (i != m_methodrefInfos.end()) {
833 return i->second;
835 sal_uInt16 index = nextConstantPoolIndex(1);
836 appendU1(m_constantPool, 10);
837 appendU2(m_constantPool, classIndex);
838 appendU2(m_constantPool, nameAndTypeIndex);
839 if (!m_methodrefInfos.insert(
840 std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
842 OSL_ASSERT(false);
844 return index;
847 sal_uInt16 ClassFile::addInterfaceMethodrefInfo(
848 rtl::OString const & type, rtl::OString const & name,
849 rtl::OString const & descriptor)
851 sal_uInt16 classIndex = addClassInfo(type);
852 sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
853 sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
854 | nameAndTypeIndex;
855 std::map< sal_uInt32, sal_uInt16 >::iterator i(
856 m_interfaceMethodrefInfos.find(key));
857 if (i != m_interfaceMethodrefInfos.end()) {
858 return i->second;
860 sal_uInt16 index = nextConstantPoolIndex(1);
861 appendU1(m_constantPool, 11);
862 appendU2(m_constantPool, classIndex);
863 appendU2(m_constantPool, nameAndTypeIndex);
864 if (!m_interfaceMethodrefInfos.insert(
865 std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
867 OSL_ASSERT(false);
869 return index;
872 sal_uInt16 ClassFile::addNameAndTypeInfo(
873 rtl::OString const & name, rtl::OString const & descriptor)
875 sal_uInt16 nameIndex = addUtf8Info(name);
876 sal_uInt16 descriptorIndex = addUtf8Info(descriptor);
877 sal_uInt32 key = (static_cast< sal_uInt32 >(nameIndex) << 16)
878 | descriptorIndex;
879 std::map< sal_uInt32, sal_uInt16 >::iterator i(
880 m_nameAndTypeInfos.find(key));
881 if (i != m_nameAndTypeInfos.end()) {
882 return i->second;
884 sal_uInt16 index = nextConstantPoolIndex(1);
885 appendU1(m_constantPool, 12);
886 appendU2(m_constantPool, nameIndex);
887 appendU2(m_constantPool, descriptorIndex);
888 if (!m_nameAndTypeInfos.insert(
889 std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
891 OSL_ASSERT(false);
893 return index;
896 void ClassFile::appendSignatureAttribute(
897 std::vector< unsigned char > & stream, rtl::OString const & signature)
899 if (signature.getLength() != 0) {
900 appendU2(
901 stream,
902 addUtf8Info(rtl::OString(RTL_CONSTASCII_STRINGPARAM("Signature"))));
903 appendU4(stream, 2);
904 appendU2(stream, addUtf8Info(signature));