1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: classfile.cxx,v $
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"
50 using codemaker::javamaker::ClassFile
;
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));
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();
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()
126 write(file
, &stream
[0], static_cast< sal_uInt64
>(n
));
132 ClassFile::Code::~Code() {}
134 void ClassFile::Code::instrAastore() {
136 appendU1(m_code
, 0x53);
139 void ClassFile::Code::instrAconstNull() {
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() {
152 appendU1(m_code
, 0xB0);
155 void ClassFile::Code::instrAthrow() {
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() {
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);
188 ClassFile::Code::Branch
ClassFile::Code::instrIfeq() {
189 // ifeq <branchbyte1> <branchbyte2>:
190 Branch branch
= m_code
.size();
191 appendU1(m_code
, 0x99);
196 ClassFile::Code::Branch
ClassFile::Code::instrIfnull() {
197 // ifnull <branchbyte1> <branchbyte2>:
198 Branch branch
= m_code
.size();
199 appendU1(m_code
, 0xC6);
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);
217 m_code
, m_classFile
.addInterfaceMethodrefInfo(type
, name
, descriptor
));
218 appendU1(m_code
, args
);
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(
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
) {
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(
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
));
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(
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
) {
299 sort
>= codemaker::UnoType::SORT_BOOLEAN
300 && sort
<= codemaker::UnoType::SORT_CHAR
);
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() {
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() {
333 appendU1(m_code
, 0xB1);
336 void ClassFile::Code::instrSwap() {
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
) {
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
);
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
)
366 appendU4(m_code
, defaultOffset
);
368 appendU4(m_code
, static_cast< sal_uInt32
>(pos2
- pos1
));
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
)
378 appendStream(m_code
, (*i
)->m_code
);
383 void ClassFile::Code::loadIntegerConstant(sal_Int32 value
) {
384 if (value
>= -1 && value
<= 5) {
386 appendU1(m_code
, static_cast< sal_uInt8
>(0x02 + value
+ 1));
387 } else if (value
>= -128 && value
<= 127) {
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
));
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
);
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(
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
));
449 appendU2(m_exceptionTable
, static_cast< sal_uInt16
>(end
));
451 appendU2(m_exceptionTable
, static_cast< sal_uInt16
>(handler
));
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
) {
467 appendU1(m_code
, 0x12);
468 appendU1(m_code
, static_cast< sal_uInt8
>(index
));
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
)
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
));
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) {
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()) {
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
)
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()) {
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
)
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()) {
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
)
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()) {
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
)
586 void ClassFile::addInterface(rtl::OString
const & interface
) {
587 if (m_interfacesCount
== SAL_MAX_UINT16
) {
588 throw CannotDumpException(
590 RTL_CONSTASCII_STRINGPARAM(
591 "Too many interfaces for Java class file format")));
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(
605 RTL_CONSTASCII_STRINGPARAM(
606 "Too many fields for Java class file format")));
609 appendU2(m_fields
, static_cast< sal_uInt16
>(accessFlags
));
610 appendU2(m_fields
, addUtf8Info(name
));
611 appendU2(m_fields
, addUtf8Info(descriptor
));
614 ((constantValueIndex
== 0 ? 0 : 1)
615 + (signature
.getLength() == 0 ? 0 : 1)));
616 if (constantValueIndex
!= 0) {
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(
636 RTL_CONSTASCII_STRINGPARAM(
637 "Too many methods for Java class file format")));
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(
647 RTL_CONSTASCII_STRINGPARAM(
648 "Too many exception specifications for Java class file"
653 ((code
== 0 ? 0 : 1) + (exceptions
.empty() ? 0 : 1)
654 + (signature
.getLength() == 0 ? 0 : 1)));
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(
666 RTL_CONSTASCII_STRINGPARAM(
667 "Code block is too big for Java class file format")));
671 addUtf8Info(rtl::OString(RTL_CONSTASCII_STRINGPARAM("Code"))));
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()) {
688 rtl::OString(RTL_CONSTASCII_STRINGPARAM("Exceptions"))));
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);
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(
726 RTL_CONSTASCII_STRINGPARAM(
727 "Too many constant pool items for Java class file"
730 sal_uInt16 index
= m_constantPoolCount
;
731 m_constantPoolCount
= m_constantPoolCount
+ width
;
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()) {
740 if (value
.getLength() > SAL_MAX_UINT16
) {
741 throw CannotDumpException(
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
)).
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()) {
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
)).
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()) {
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
)).
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)
807 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(m_fieldrefInfos
.find(key
));
808 if (i
!= m_fieldrefInfos
.end()) {
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
)
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)
831 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(m_methodrefInfos
.find(key
));
832 if (i
!= m_methodrefInfos
.end()) {
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
)
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)
855 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(
856 m_interfaceMethodrefInfos
.find(key
));
857 if (i
!= m_interfaceMethodrefInfos
.end()) {
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
)
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)
879 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(
880 m_nameAndTypeInfos
.find(key
));
881 if (i
!= m_nameAndTypeInfos
.end()) {
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
)
896 void ClassFile::appendSignatureAttribute(
897 std::vector
< unsigned char > & stream
, rtl::OString
const & signature
)
899 if (signature
.getLength() != 0) {
902 addUtf8Info(rtl::OString(RTL_CONSTASCII_STRINGPARAM("Signature"))));
904 appendU2(stream
, addUtf8Info(signature
));