1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "classfile.hxx"
23 #include "codemaker/global.hxx"
24 #include "codemaker/options.hxx"
25 #include "codemaker/unotype.hxx"
27 #include "boost/static_assert.hpp"
28 #include "osl/diagnose.h"
29 #include "rtl/string.h"
30 #include "rtl/string.hxx"
31 #include "sal/types.h"
37 using codemaker::javamaker::ClassFile
;
41 void appendU1(std::vector
< unsigned char > & stream
, sal_uInt8 data
) {
42 stream
.push_back(static_cast< unsigned char >(data
));
45 void appendU2(std::vector
< unsigned char > & stream
, sal_uInt16 data
) {
46 stream
.push_back(static_cast< unsigned char >(data
>> 8));
47 stream
.push_back(static_cast< unsigned char >(data
& 0xFF));
50 void appendU4(std::vector
< unsigned char > & stream
, sal_uInt32 data
) {
51 stream
.push_back(static_cast< unsigned char >(data
>> 24));
52 stream
.push_back(static_cast< unsigned char >((data
>> 16) & 0xFF));
53 stream
.push_back(static_cast< unsigned char >((data
>> 8) & 0xFF));
54 stream
.push_back(static_cast< unsigned char >(data
& 0xFF));
57 void appendU8(std::vector
< unsigned char > & stream
, sal_uInt64 data
) {
58 stream
.push_back(static_cast< unsigned char >(data
>> 56));
59 stream
.push_back(static_cast< unsigned char >((data
>> 48) & 0xFF));
60 stream
.push_back(static_cast< unsigned char >((data
>> 40) & 0xFF));
61 stream
.push_back(static_cast< unsigned char >((data
>> 32) & 0xFF));
62 stream
.push_back(static_cast< unsigned char >((data
>> 24) & 0xFF));
63 stream
.push_back(static_cast< unsigned char >((data
>> 16) & 0xFF));
64 stream
.push_back(static_cast< unsigned char >((data
>> 8) & 0xFF));
65 stream
.push_back(static_cast< unsigned char >(data
& 0xFF));
69 std::vector
< unsigned char > & stream
,
70 std::vector
< unsigned char > const & data
)
72 stream
.insert(stream
.end(), data
.begin(), data
.end());
75 void write(FileStream
& file
, void const * buffer
, sal_uInt64 size
) {
76 if (!file
.write(buffer
, size
))
77 throw CannotDumpException("Error writing file");
80 void writeU2(FileStream
& file
, sal_uInt16 data
) {
81 unsigned char buf
[] = {
82 static_cast< unsigned char >(data
>> 8),
83 static_cast< unsigned char >(data
& 0xFF) };
84 write(file
, buf
, sizeof buf
);
87 void writeU4(FileStream
& file
, sal_uInt32 data
) {
88 unsigned char buf
[] = {
89 static_cast< unsigned char >(data
>> 24),
90 static_cast< unsigned char >((data
>> 16) & 0xFF),
91 static_cast< unsigned char >((data
>> 8) & 0xFF),
92 static_cast< unsigned char >(data
& 0xFF) };
93 write(file
, buf
, sizeof buf
);
96 void writeStream(FileStream
& file
, std::vector
< unsigned char > const & stream
)
98 std::vector
< unsigned char >::size_type n
= stream
.size();
100 sizeof (std::vector
< unsigned char >::size_type
)
101 <= sizeof (sal_uInt64
));
102 // both unsigned integral, so sizeof is a practically sufficient
103 // approximation of std::numeric_limits<T1>::max() <=
104 // std::numeric_limits<T2>::max()
106 write(file
, &stream
[0], static_cast< sal_uInt64
>(n
));
112 ClassFile::Code::~Code() {}
114 void ClassFile::Code::instrAastore() {
116 appendU1(m_code
, 0x53);
119 void ClassFile::Code::instrAconstNull() {
121 appendU1(m_code
, 0x01);
124 void ClassFile::Code::instrAnewarray(OString
const & type
) {
125 // anewarray <indexbyte1> <indexbyte2>:
126 appendU1(m_code
, 0xBD);
127 appendU2(m_code
, m_classFile
.addClassInfo(type
));
130 void ClassFile::Code::instrAreturn() {
132 appendU1(m_code
, 0xB0);
135 void ClassFile::Code::instrAthrow() {
137 appendU1(m_code
, 0xBF);
140 void ClassFile::Code::instrCheckcast(OString
const & type
) {
141 // checkcast <indexbyte1> <indexbyte2>:
142 appendU1(m_code
, 0xC0);
143 appendU2(m_code
, m_classFile
.addClassInfo(type
));
146 void ClassFile::Code::instrDup() {
148 appendU1(m_code
, 0x59);
151 void ClassFile::Code::instrGetstatic(
152 OString
const & type
, OString
const & name
,
153 OString
const & descriptor
)
155 // getstatic <indexbyte1> <indexbyte2>:
156 appendU1(m_code
, 0xB2);
157 appendU2(m_code
, m_classFile
.addFieldrefInfo(type
, name
, descriptor
));
160 ClassFile::Code::Branch
ClassFile::Code::instrIfAcmpne() {
161 // if_acmpne <branchbyte1> <branchbyte2>:
162 Branch branch
= m_code
.size();
163 appendU1(m_code
, 0xA6);
168 ClassFile::Code::Branch
ClassFile::Code::instrIfeq() {
169 // ifeq <branchbyte1> <branchbyte2>:
170 Branch branch
= m_code
.size();
171 appendU1(m_code
, 0x99);
176 ClassFile::Code::Branch
ClassFile::Code::instrIfnull() {
177 // ifnull <branchbyte1> <branchbyte2>:
178 Branch branch
= m_code
.size();
179 appendU1(m_code
, 0xC6);
184 void ClassFile::Code::instrInstanceof(OString
const & type
) {
185 // instanceof <indexbyte1> <indexbyte2>:
186 appendU1(m_code
, 0xC1);
187 appendU2(m_code
, m_classFile
.addClassInfo(type
));
190 void ClassFile::Code::instrInvokeinterface(
191 OString
const & type
, OString
const & name
,
192 OString
const & descriptor
, sal_uInt8 args
)
194 // invokeinterface <indexbyte1> <indexbyte2> <nargs> 0:
195 appendU1(m_code
, 0xB9);
197 m_code
, m_classFile
.addInterfaceMethodrefInfo(type
, name
, descriptor
));
198 appendU1(m_code
, args
);
202 void ClassFile::Code::instrInvokespecial(
203 OString
const & type
, OString
const & name
,
204 OString
const & descriptor
)
206 // invokespecial <indexbyte1> <indexbyte2>:
207 appendU1(m_code
, 0xB7);
208 appendU2(m_code
, m_classFile
.addMethodrefInfo(type
, name
, descriptor
));
211 void ClassFile::Code::instrInvokestatic(
212 OString
const & type
, OString
const & name
,
213 OString
const & descriptor
)
215 // invokestatic <indexbyte1> <indexbyte2>:
216 appendU1(m_code
, 0xB8);
217 appendU2(m_code
, m_classFile
.addMethodrefInfo(type
, name
, descriptor
));
220 void ClassFile::Code::instrInvokevirtual(
221 OString
const & type
, OString
const & name
,
222 OString
const & descriptor
)
224 // invokevirtual <indexbyte1> <indexbyte2>:
225 appendU1(m_code
, 0xB6);
226 appendU2(m_code
, m_classFile
.addMethodrefInfo(type
, name
, descriptor
));
229 void ClassFile::Code::instrLookupswitch(
230 Code
const * defaultBlock
,
231 std::list
< std::pair
< sal_Int32
, Code
* > > const & blocks
)
233 // lookupswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
234 // <defaultbyte4> <npairs1> <npairs2> <npairs3> <npairs4>
235 // <match--offset pairs...>:
236 std::list
< std::pair
< sal_Int32
, Code
* > >::size_type size
= blocks
.size();
237 if (size
> SAL_MAX_INT32
) {
238 throw CannotDumpException("Lookup-switch too large for Java class file format");
240 Position pos1
= m_code
.size();
241 appendU1(m_code
, 0xAB);
242 int pad
= (pos1
+ 1) % 4;
243 for (int i
= 0; i
< pad
; ++i
) {
246 Position pos2
= pos1
+ 1 + pad
+ 8 + blocks
.size() * 8; //FIXME: overflow
247 appendU4(m_code
, static_cast< sal_uInt32
>(pos2
- pos1
)); //FIXME: overflow
248 pos2
+= defaultBlock
->m_code
.size(); //FIXME: overflow
249 appendU4(m_code
, static_cast< sal_uInt32
>(size
));
250 for (std::list
< std::pair
< sal_Int32
, Code
* > >::const_iterator
i(
252 i
!= blocks
.end(); ++i
)
254 appendU4(m_code
, static_cast< sal_uInt32
>(i
->first
));
255 appendU4(m_code
, static_cast< sal_uInt32
>(pos2
- pos1
));
257 pos2
+= i
->second
->m_code
.size(); //FIXME: overflow
259 appendStream(m_code
, defaultBlock
->m_code
);
260 for (std::list
< std::pair
< sal_Int32
, Code
* > >::const_iterator
i(
262 i
!= blocks
.end(); ++i
)
264 appendStream(m_code
, i
->second
->m_code
);
268 void ClassFile::Code::instrNew(OString
const & type
) {
269 // new <indexbyte1> <indexbyte2>:
270 appendU1(m_code
, 0xBB);
271 appendU2(m_code
, m_classFile
.addClassInfo(type
));
274 void ClassFile::Code::instrNewarray(codemaker::UnoType::Sort sort
) {
276 sort
>= codemaker::UnoType::SORT_BOOLEAN
277 && sort
<= codemaker::UnoType::SORT_CHAR
);
279 appendU1(m_code
, 0xBC);
280 static sal_uInt8
const atypes
[codemaker::UnoType::SORT_CHAR
] = {
281 0x04, 0x08, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x06, 0x07, 0x05 };
282 appendU1(m_code
, atypes
[sort
- 1]);
285 void ClassFile::Code::instrPop() {
287 appendU1(m_code
, 0x57);
290 void ClassFile::Code::instrPutfield(
291 OString
const & type
, OString
const & name
,
292 OString
const & descriptor
)
294 // putfield <indexbyte1> <indexbyte2>:
295 appendU1(m_code
, 0xB5);
296 appendU2(m_code
, m_classFile
.addFieldrefInfo(type
, name
, descriptor
));
299 void ClassFile::Code::instrPutstatic(
300 OString
const & type
, OString
const & name
,
301 OString
const & descriptor
)
303 // putstatic <indexbyte1> <indexbyte2>:
304 appendU1(m_code
, 0xB3);
305 appendU2(m_code
, m_classFile
.addFieldrefInfo(type
, name
, descriptor
));
308 void ClassFile::Code::instrReturn() {
310 appendU1(m_code
, 0xB1);
313 void ClassFile::Code::instrSwap() {
315 appendU1(m_code
, 0x5F);
318 void ClassFile::Code::instrTableswitch(
319 Code
const * defaultBlock
, sal_Int32 low
,
320 std::list
< Code
* > const & blocks
)
322 // tableswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
323 // <defaultbyte4> <lowbyte1> <lowbyte2> <lowbyte3> <lowbyte4> <highbyte1>
324 // <highbyte2> <highbyte3> <highbyte4> <jump offsets...>:
325 Position pos1
= m_code
.size();
326 appendU1(m_code
, 0xAA);
327 int pad
= (pos1
+ 1) % 4;
328 for (int i
= 0; i
< pad
; ++i
) {
331 std::list
< Code
* >::size_type size
= blocks
.size();
332 Position pos2
= pos1
+ 1 + pad
+ 12 + size
* 4; //FIXME: overflow
333 sal_uInt32 defaultOffset
= static_cast< sal_uInt32
>(pos2
- pos1
);
335 appendU4(m_code
, defaultOffset
);
336 pos2
+= defaultBlock
->m_code
.size(); //FIXME: overflow
337 appendU4(m_code
, static_cast< sal_uInt32
>(low
));
338 appendU4(m_code
, static_cast< sal_uInt32
>(low
+ (size
- 1)));
339 for (std::list
< Code
* >::const_iterator
i(blocks
.begin());
340 i
!= blocks
.end(); ++i
)
343 appendU4(m_code
, defaultOffset
);
345 appendU4(m_code
, static_cast< sal_uInt32
>(pos2
- pos1
));
347 pos2
+= (*i
)->m_code
.size(); //FIXME: overflow
350 appendStream(m_code
, defaultBlock
->m_code
);
351 for (std::list
< Code
* >::const_iterator
i(blocks
.begin());
352 i
!= blocks
.end(); ++i
)
355 appendStream(m_code
, (*i
)->m_code
);
360 void ClassFile::Code::loadIntegerConstant(sal_Int32 value
) {
361 if (value
>= -1 && value
<= 5) {
363 appendU1(m_code
, static_cast< sal_uInt8
>(0x02 + value
+ 1));
364 } else if (value
>= -128 && value
<= 127) {
366 appendU1(m_code
, 0x10);
367 appendU1(m_code
, static_cast< sal_uInt8
>(value
));
368 } else if (value
>= -32768 && value
<= 32767) {
369 // sipush <byte1> <byte2>:
370 appendU1(m_code
, 0x11);
371 appendU2(m_code
, static_cast< sal_uInt16
>(value
));
373 ldc(m_classFile
.addIntegerInfo(value
));
377 void ClassFile::Code::loadStringConstant(OString
const & value
) {
378 ldc(m_classFile
.addStringInfo(value
));
381 void ClassFile::Code::loadLocalInteger(sal_uInt16 index
) {
382 accessLocal(index
, 0x1A, 0x15); // iload_<n>, iload
385 void ClassFile::Code::loadLocalLong(sal_uInt16 index
) {
386 accessLocal(index
, 0x1E, 0x16); // load_<n>, load
389 void ClassFile::Code::loadLocalFloat(sal_uInt16 index
) {
390 accessLocal(index
, 0x22, 0x17); // load_<n>, load
393 void ClassFile::Code::loadLocalDouble(sal_uInt16 index
) {
394 accessLocal(index
, 0x26, 0x18); // load_<n>, load
397 void ClassFile::Code::loadLocalReference(sal_uInt16 index
) {
398 accessLocal(index
, 0x2A, 0x19); // aload_<n>, aload
401 void ClassFile::Code::storeLocalReference(sal_uInt16 index
) {
402 accessLocal(index
, 0x4B, 0x3A); // astore_<n>, astore
405 void ClassFile::Code::branchHere(Branch branch
) {
406 std::vector
< unsigned char >::size_type n
= m_code
.size();
407 OSL_ASSERT(n
> branch
&& n
- branch
<= SAL_MAX_INT16
);
409 m_code
[branch
+ 1] = static_cast< sal_uInt8
>(n
>> 8);
410 m_code
[branch
+ 2] = static_cast< sal_uInt8
>(n
& 0xFF);
413 void ClassFile::Code::addException(
414 Position start
, Position end
, Position handler
, OString
const & type
)
416 OSL_ASSERT(start
< end
&& end
<= m_code
.size() && handler
<= m_code
.size());
417 if (m_exceptionTableLength
== SAL_MAX_UINT16
) {
418 throw CannotDumpException("Too many exception handlers for Java class file format");
420 ++m_exceptionTableLength
;
421 appendU2(m_exceptionTable
, static_cast< sal_uInt16
>(start
));
423 appendU2(m_exceptionTable
, static_cast< sal_uInt16
>(end
));
425 appendU2(m_exceptionTable
, static_cast< sal_uInt16
>(handler
));
427 appendU2(m_exceptionTable
, m_classFile
.addClassInfo(type
));
430 ClassFile::Code::Position
ClassFile::Code::getPosition() const {
431 return m_code
.size();
434 ClassFile::Code::Code(ClassFile
& classFile
):
435 m_classFile(classFile
), m_exceptionTableLength(0)
438 void ClassFile::Code::ldc(sal_uInt16 index
) {
441 appendU1(m_code
, 0x12);
442 appendU1(m_code
, static_cast< sal_uInt8
>(index
));
444 // ldc_w <indexbyte1> <indexbyte2>:
445 appendU1(m_code
, 0x13);
446 appendU2(m_code
, index
);
450 void ClassFile::Code::accessLocal(
451 sal_uInt16 index
, sal_uInt8 fastOp
, sal_uInt8 normalOp
)
454 // ...load/store_<n>:
455 appendU1(m_code
, static_cast< sal_uInt8
>(fastOp
+ index
));
456 } else if (index
<= 0xFF) {
457 // ...load/store <index>:
458 appendU1(m_code
, normalOp
);
459 appendU1(m_code
, static_cast< sal_uInt8
>(index
));
461 // wide ...load/store <indexbyte1> <indexbyte2>:
462 appendU1(m_code
, 0xC4);
463 appendU1(m_code
, normalOp
);
464 appendU2(m_code
, index
);
468 ClassFile::ClassFile(
469 AccessFlags accessFlags
, OString
const & thisClass
,
470 OString
const & superClass
, OString
const & signature
):
471 m_constantPoolCount(1), m_accessFlags(accessFlags
), m_interfacesCount(0),
472 m_fieldsCount(0), m_methodsCount(0), m_attributesCount(0)
474 m_thisClass
= addClassInfo(thisClass
);
475 m_superClass
= addClassInfo(superClass
);
476 if (!signature
.isEmpty()) {
478 appendU2(m_attributes
, addUtf8Info("Signature"));
479 appendU4(m_attributes
, 2);
480 appendU2(m_attributes
, addUtf8Info(signature
));
484 ClassFile::~ClassFile() {}
486 ClassFile::Code
* ClassFile::newCode() {
487 return new Code(*this);
490 sal_uInt16
ClassFile::addIntegerInfo(sal_Int32 value
) {
491 std::map
< sal_Int32
, sal_uInt16
>::iterator
i(m_integerInfos
.find(value
));
492 if (i
!= m_integerInfos
.end()) {
495 sal_uInt16 index
= nextConstantPoolIndex(1);
496 appendU1(m_constantPool
, 3);
497 appendU4(m_constantPool
, static_cast< sal_uInt32
>(value
));
498 if (!m_integerInfos
.insert(
499 std::map
< sal_Int32
, sal_uInt16
>::value_type(value
, index
)).second
)
506 sal_uInt16
ClassFile::addFloatInfo(float value
) {
507 std::map
< float, sal_uInt16
>::iterator
i(m_floatInfos
.find(value
));
508 if (i
!= m_floatInfos
.end()) {
511 sal_uInt16 index
= nextConstantPoolIndex(1);
512 appendU1(m_constantPool
, 4);
513 union { float floatBytes
; sal_uInt32 uint32Bytes
; } bytes
;
514 bytes
.floatBytes
= value
;
515 appendU4(m_constantPool
, bytes
.uint32Bytes
);
516 if (!m_floatInfos
.insert(
517 std::map
< float, sal_uInt16
>::value_type(value
, index
)).second
)
524 sal_uInt16
ClassFile::addLongInfo(sal_Int64 value
) {
525 std::map
< sal_Int64
, sal_uInt16
>::iterator
i(m_longInfos
.find(value
));
526 if (i
!= m_longInfos
.end()) {
529 sal_uInt16 index
= nextConstantPoolIndex(2);
530 appendU1(m_constantPool
, 5);
531 appendU8(m_constantPool
, static_cast< sal_uInt64
>(value
));
532 if (!m_longInfos
.insert(
533 std::map
< sal_Int64
, sal_uInt16
>::value_type(value
, index
)).second
)
540 sal_uInt16
ClassFile::addDoubleInfo(double value
) {
541 std::map
< double, sal_uInt16
>::iterator
i(m_doubleInfos
.find(value
));
542 if (i
!= m_doubleInfos
.end()) {
545 sal_uInt16 index
= nextConstantPoolIndex(2);
546 appendU1(m_constantPool
, 6);
547 union { double doubleBytes
; sal_uInt64 uint64Bytes
; } bytes
;
548 bytes
.doubleBytes
= value
;
549 appendU8(m_constantPool
, bytes
.uint64Bytes
);
550 if (!m_doubleInfos
.insert(
551 std::map
< double, sal_uInt16
>::value_type(value
, index
)).second
)
558 void ClassFile::addInterface(OString
const & interface
) {
559 if (m_interfacesCount
== SAL_MAX_UINT16
) {
560 throw CannotDumpException("Too many interfaces for Java class file format");
563 appendU2(m_interfaces
, addClassInfo(interface
));
566 void ClassFile::addField(
567 AccessFlags accessFlags
, OString
const & name
,
568 OString
const & descriptor
, sal_uInt16 constantValueIndex
,
569 OString
const & signature
)
571 if (m_fieldsCount
== SAL_MAX_UINT16
) {
572 throw CannotDumpException("Too many fields for Java class file format");
575 appendU2(m_fields
, static_cast< sal_uInt16
>(accessFlags
));
576 appendU2(m_fields
, addUtf8Info(name
));
577 appendU2(m_fields
, addUtf8Info(descriptor
));
580 ((constantValueIndex
== 0 ? 0 : 1)
581 + (signature
.isEmpty() ? 0 : 1)));
582 if (constantValueIndex
!= 0) {
583 appendU2(m_fields
, addUtf8Info("ConstantValue"));
584 appendU4(m_fields
, 2);
585 appendU2(m_fields
, constantValueIndex
);
587 appendSignatureAttribute(m_fields
, signature
);
590 void ClassFile::addMethod(
591 AccessFlags accessFlags
, OString
const & name
,
592 OString
const & descriptor
, Code
const * code
,
593 std::vector
< OString
> const & exceptions
,
594 OString
const & signature
)
596 if (m_methodsCount
== SAL_MAX_UINT16
) {
597 throw CannotDumpException("Too many methods for Java class file format");
600 appendU2(m_methods
, static_cast< sal_uInt16
>(accessFlags
));
601 appendU2(m_methods
, addUtf8Info(name
));
602 appendU2(m_methods
, addUtf8Info(descriptor
));
603 std::vector
< OString
>::size_type excs
= exceptions
.size();
604 if (excs
> SAL_MAX_UINT16
) {
605 throw CannotDumpException("Too many exception specifications for Java class file format");
609 ((code
== 0 ? 0 : 1) + (exceptions
.empty() ? 0 : 1)
610 + (signature
.isEmpty() ? 0 : 1)));
612 std::vector
< unsigned char >::size_type codeSize
= code
->m_code
.size();
613 std::vector
< unsigned char >::size_type exceptionTableSize
614 = code
->m_exceptionTable
.size();
615 if (codeSize
> SAL_MAX_UINT32
- (2 + 2 + 4 + 2 + 2)
616 || (exceptionTableSize
617 > (SAL_MAX_UINT32
- (2 + 2 + 4 + 2 + 2)
618 - static_cast< sal_uInt32
>(codeSize
))))
620 throw CannotDumpException("Code block is too big for Java class file format");
622 appendU2(m_methods
, addUtf8Info("Code"));
625 (2 + 2 + 4 + static_cast< sal_uInt32
>(codeSize
) + 2
626 + static_cast< sal_uInt32
>(exceptionTableSize
) + 2));
627 appendU2(m_methods
, code
->m_maxStack
);
628 appendU2(m_methods
, code
->m_maxLocals
);
629 appendU4(m_methods
, static_cast< sal_uInt32
>(codeSize
));
630 appendStream(m_methods
, code
->m_code
);
631 appendU2(m_methods
, code
->m_exceptionTableLength
);
632 appendStream(m_methods
, code
->m_exceptionTable
);
633 appendU2(m_methods
, 0);
635 if (!exceptions
.empty()) {
636 appendU2(m_methods
, addUtf8Info("Exceptions"));
639 static_cast< sal_uInt32
>(2 + 2 * static_cast< sal_uInt32
>(excs
)));
640 appendU2(m_methods
, static_cast< sal_uInt16
>(excs
));
641 for (std::vector
< OString
>::const_iterator
i(exceptions
.begin());
642 i
!= exceptions
.end(); ++i
)
644 appendU2(m_methods
, addClassInfo(*i
));
647 appendSignatureAttribute(m_methods
, signature
);
650 void ClassFile::write(FileStream
& file
) const {
651 writeU4(file
, 0xCAFEBABE);
653 writeU2(file
, 49); // class file version of JRE 1.5
654 writeU2(file
, m_constantPoolCount
);
655 writeStream(file
, m_constantPool
);
656 writeU2(file
, static_cast< sal_uInt16
>(m_accessFlags
));
657 writeU2(file
, m_thisClass
);
658 writeU2(file
, m_superClass
);
659 writeU2(file
, m_interfacesCount
);
660 writeStream(file
, m_interfaces
);
661 writeU2(file
, m_fieldsCount
);
662 writeStream(file
, m_fields
);
663 writeU2(file
, m_methodsCount
);
664 writeStream(file
, m_methods
);
665 writeU2(file
, m_attributesCount
);
666 writeStream(file
, m_attributes
);
669 sal_uInt16
ClassFile::nextConstantPoolIndex(sal_uInt16 width
) {
670 OSL_ASSERT(width
== 1 || width
== 2);
671 if (m_constantPoolCount
> SAL_MAX_UINT16
- width
) {
672 throw CannotDumpException("Too many constant pool items for Java class file format");
674 sal_uInt16 index
= m_constantPoolCount
;
675 m_constantPoolCount
= m_constantPoolCount
+ width
;
679 sal_uInt16
ClassFile::addUtf8Info(OString
const & value
) {
680 std::map
< OString
, sal_uInt16
>::iterator
i(m_utf8Infos
.find(value
));
681 if (i
!= m_utf8Infos
.end()) {
684 if (value
.getLength() > SAL_MAX_UINT16
) {
685 throw CannotDumpException("UTF-8 string too long for Java class file format");
687 sal_uInt16 index
= nextConstantPoolIndex(1);
688 appendU1(m_constantPool
, 1);
689 appendU2(m_constantPool
, static_cast< sal_uInt16
>(value
.getLength()));
690 for (sal_Int32 j
= 0; j
< value
.getLength(); ++j
) {
691 appendU1(m_constantPool
, static_cast< sal_uInt8
>(value
[j
]));
693 if (!m_utf8Infos
.insert(
694 std::map
< OString
, sal_uInt16
>::value_type(value
, index
)).
702 sal_uInt16
ClassFile::addClassInfo(OString
const & type
) {
703 sal_uInt16 nameIndex
= addUtf8Info(type
);
704 std::map
< sal_uInt16
, sal_uInt16
>::iterator
i(
705 m_classInfos
.find(nameIndex
));
706 if (i
!= m_classInfos
.end()) {
709 sal_uInt16 index
= nextConstantPoolIndex(1);
710 appendU1(m_constantPool
, 7);
711 appendU2(m_constantPool
, nameIndex
);
712 if (!m_classInfos
.insert(
713 std::map
< sal_uInt16
, sal_uInt16
>::value_type(nameIndex
, index
)).
721 sal_uInt16
ClassFile::addStringInfo(OString
const & value
) {
722 sal_uInt16 stringIndex
= addUtf8Info(value
);
723 std::map
< sal_uInt16
, sal_uInt16
>::iterator
i(
724 m_stringInfos
.find(stringIndex
));
725 if (i
!= m_stringInfos
.end()) {
728 sal_uInt16 index
= nextConstantPoolIndex(1);
729 appendU1(m_constantPool
, 8);
730 appendU2(m_constantPool
, stringIndex
);
731 if (!m_stringInfos
.insert(
732 std::map
< sal_uInt16
, sal_uInt16
>::value_type(stringIndex
, index
)).
740 sal_uInt16
ClassFile::addFieldrefInfo(
741 OString
const & type
, OString
const & name
,
742 OString
const & descriptor
)
744 sal_uInt16 classIndex
= addClassInfo(type
);
745 sal_uInt16 nameAndTypeIndex
= addNameAndTypeInfo(name
, descriptor
);
746 sal_uInt32 key
= (static_cast< sal_uInt32
>(classIndex
) << 16)
748 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(m_fieldrefInfos
.find(key
));
749 if (i
!= m_fieldrefInfos
.end()) {
752 sal_uInt16 index
= nextConstantPoolIndex(1);
753 appendU1(m_constantPool
, 9);
754 appendU2(m_constantPool
, classIndex
);
755 appendU2(m_constantPool
, nameAndTypeIndex
);
756 if (!m_fieldrefInfos
.insert(
757 std::map
< sal_uInt32
, sal_uInt16
>::value_type(key
, index
)).second
)
764 sal_uInt16
ClassFile::addMethodrefInfo(
765 OString
const & type
, OString
const & name
,
766 OString
const & descriptor
)
768 sal_uInt16 classIndex
= addClassInfo(type
);
769 sal_uInt16 nameAndTypeIndex
= addNameAndTypeInfo(name
, descriptor
);
770 sal_uInt32 key
= (static_cast< sal_uInt32
>(classIndex
) << 16)
772 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(m_methodrefInfos
.find(key
));
773 if (i
!= m_methodrefInfos
.end()) {
776 sal_uInt16 index
= nextConstantPoolIndex(1);
777 appendU1(m_constantPool
, 10);
778 appendU2(m_constantPool
, classIndex
);
779 appendU2(m_constantPool
, nameAndTypeIndex
);
780 if (!m_methodrefInfos
.insert(
781 std::map
< sal_uInt32
, sal_uInt16
>::value_type(key
, index
)).second
)
788 sal_uInt16
ClassFile::addInterfaceMethodrefInfo(
789 OString
const & type
, OString
const & name
,
790 OString
const & descriptor
)
792 sal_uInt16 classIndex
= addClassInfo(type
);
793 sal_uInt16 nameAndTypeIndex
= addNameAndTypeInfo(name
, descriptor
);
794 sal_uInt32 key
= (static_cast< sal_uInt32
>(classIndex
) << 16)
796 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(
797 m_interfaceMethodrefInfos
.find(key
));
798 if (i
!= m_interfaceMethodrefInfos
.end()) {
801 sal_uInt16 index
= nextConstantPoolIndex(1);
802 appendU1(m_constantPool
, 11);
803 appendU2(m_constantPool
, classIndex
);
804 appendU2(m_constantPool
, nameAndTypeIndex
);
805 if (!m_interfaceMethodrefInfos
.insert(
806 std::map
< sal_uInt32
, sal_uInt16
>::value_type(key
, index
)).second
)
813 sal_uInt16
ClassFile::addNameAndTypeInfo(
814 OString
const & name
, OString
const & descriptor
)
816 sal_uInt16 nameIndex
= addUtf8Info(name
);
817 sal_uInt16 descriptorIndex
= addUtf8Info(descriptor
);
818 sal_uInt32 key
= (static_cast< sal_uInt32
>(nameIndex
) << 16)
820 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(
821 m_nameAndTypeInfos
.find(key
));
822 if (i
!= m_nameAndTypeInfos
.end()) {
825 sal_uInt16 index
= nextConstantPoolIndex(1);
826 appendU1(m_constantPool
, 12);
827 appendU2(m_constantPool
, nameIndex
);
828 appendU2(m_constantPool
, descriptorIndex
);
829 if (!m_nameAndTypeInfos
.insert(
830 std::map
< sal_uInt32
, sal_uInt16
>::value_type(key
, index
)).second
)
837 void ClassFile::appendSignatureAttribute(
838 std::vector
< unsigned char > & stream
, OString
const & signature
)
840 if (!signature
.isEmpty()) {
841 appendU2(stream
, addUtf8Info("Signature"));
843 appendU2(stream
, addUtf8Info(signature
));
847 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */