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 <osl/diagnose.h>
28 #include <rtl/string.h>
29 #include <rtl/string.hxx>
30 #include <sal/types.h>
36 using codemaker::javamaker::ClassFile
;
40 void appendU1(std::vector
< unsigned char > & stream
, sal_uInt8 data
) {
41 stream
.push_back(static_cast< unsigned char >(data
));
44 void appendU2(std::vector
< unsigned char > & stream
, sal_uInt16 data
) {
45 stream
.push_back(static_cast< unsigned char >(data
>> 8));
46 stream
.push_back(static_cast< unsigned char >(data
& 0xFF));
49 void appendU4(std::vector
< unsigned char > & stream
, sal_uInt32 data
) {
50 stream
.push_back(static_cast< unsigned char >(data
>> 24));
51 stream
.push_back(static_cast< unsigned char >((data
>> 16) & 0xFF));
52 stream
.push_back(static_cast< unsigned char >((data
>> 8) & 0xFF));
53 stream
.push_back(static_cast< unsigned char >(data
& 0xFF));
56 void appendU8(std::vector
< unsigned char > & stream
, sal_uInt64 data
) {
57 stream
.push_back(static_cast< unsigned char >(data
>> 56));
58 stream
.push_back(static_cast< unsigned char >((data
>> 48) & 0xFF));
59 stream
.push_back(static_cast< unsigned char >((data
>> 40) & 0xFF));
60 stream
.push_back(static_cast< unsigned char >((data
>> 32) & 0xFF));
61 stream
.push_back(static_cast< unsigned char >((data
>> 24) & 0xFF));
62 stream
.push_back(static_cast< unsigned char >((data
>> 16) & 0xFF));
63 stream
.push_back(static_cast< unsigned char >((data
>> 8) & 0xFF));
64 stream
.push_back(static_cast< unsigned char >(data
& 0xFF));
68 std::vector
< unsigned char > & stream
,
69 std::vector
< unsigned char > const & data
)
71 stream
.insert(stream
.end(), data
.begin(), data
.end());
74 void write(FileStream
& file
, void const * buffer
, sal_uInt64 size
) {
75 if (!file
.write(buffer
, size
))
76 throw CannotDumpException("Error writing file");
79 void writeU2(FileStream
& file
, sal_uInt16 data
) {
80 unsigned char buf
[] = {
81 static_cast< unsigned char >(data
>> 8),
82 static_cast< unsigned char >(data
& 0xFF) };
83 write(file
, buf
, sizeof buf
);
86 void writeU4(FileStream
& file
, sal_uInt32 data
) {
87 unsigned char buf
[] = {
88 static_cast< unsigned char >(data
>> 24),
89 static_cast< unsigned char >((data
>> 16) & 0xFF),
90 static_cast< unsigned char >((data
>> 8) & 0xFF),
91 static_cast< unsigned char >(data
& 0xFF) };
92 write(file
, buf
, sizeof buf
);
95 void writeStream(FileStream
& file
, std::vector
< unsigned char > const & stream
)
97 std::vector
< unsigned char >::size_type n
= stream
.size();
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()
105 write(file
, &stream
[0], static_cast< sal_uInt64
>(n
));
111 ClassFile::Code::~Code() {}
113 void ClassFile::Code::instrAastore() {
115 appendU1(m_code
, 0x53);
118 void ClassFile::Code::instrAconstNull() {
120 appendU1(m_code
, 0x01);
123 void ClassFile::Code::instrAnewarray(OString
const & type
) {
124 // anewarray <indexbyte1> <indexbyte2>:
125 appendU1(m_code
, 0xBD);
126 appendU2(m_code
, m_classFile
.addClassInfo(type
));
129 void ClassFile::Code::instrAreturn() {
131 appendU1(m_code
, 0xB0);
134 void ClassFile::Code::instrAthrow() {
136 appendU1(m_code
, 0xBF);
139 void ClassFile::Code::instrCheckcast(OString
const & type
) {
140 // checkcast <indexbyte1> <indexbyte2>:
141 appendU1(m_code
, 0xC0);
142 appendU2(m_code
, m_classFile
.addClassInfo(type
));
145 void ClassFile::Code::instrDup() {
147 appendU1(m_code
, 0x59);
150 void ClassFile::Code::instrGetstatic(
151 OString
const & type
, OString
const & name
,
152 OString
const & descriptor
)
154 // getstatic <indexbyte1> <indexbyte2>:
155 appendU1(m_code
, 0xB2);
156 appendU2(m_code
, m_classFile
.addFieldrefInfo(type
, name
, descriptor
));
159 ClassFile::Code::Branch
ClassFile::Code::instrIfAcmpne() {
160 // if_acmpne <branchbyte1> <branchbyte2>:
161 Branch branch
= m_code
.size();
162 appendU1(m_code
, 0xA6);
167 ClassFile::Code::Branch
ClassFile::Code::instrIfeq() {
168 // ifeq <branchbyte1> <branchbyte2>:
169 Branch branch
= m_code
.size();
170 appendU1(m_code
, 0x99);
175 ClassFile::Code::Branch
ClassFile::Code::instrIfnull() {
176 // ifnull <branchbyte1> <branchbyte2>:
177 Branch branch
= m_code
.size();
178 appendU1(m_code
, 0xC6);
183 void ClassFile::Code::instrInstanceof(OString
const & type
) {
184 // instanceof <indexbyte1> <indexbyte2>:
185 appendU1(m_code
, 0xC1);
186 appendU2(m_code
, m_classFile
.addClassInfo(type
));
189 void ClassFile::Code::instrInvokeinterface(
190 OString
const & type
, OString
const & name
,
191 OString
const & descriptor
, sal_uInt8 args
)
193 // invokeinterface <indexbyte1> <indexbyte2> <nargs> 0:
194 appendU1(m_code
, 0xB9);
196 m_code
, m_classFile
.addInterfaceMethodrefInfo(type
, name
, descriptor
));
197 appendU1(m_code
, args
);
201 void ClassFile::Code::instrInvokespecial(
202 OString
const & type
, OString
const & name
,
203 OString
const & descriptor
)
205 // invokespecial <indexbyte1> <indexbyte2>:
206 appendU1(m_code
, 0xB7);
207 appendU2(m_code
, m_classFile
.addMethodrefInfo(type
, name
, descriptor
));
210 void ClassFile::Code::instrInvokestatic(
211 OString
const & type
, OString
const & name
,
212 OString
const & descriptor
)
214 // invokestatic <indexbyte1> <indexbyte2>:
215 appendU1(m_code
, 0xB8);
216 appendU2(m_code
, m_classFile
.addMethodrefInfo(type
, name
, descriptor
));
219 void ClassFile::Code::instrInvokevirtual(
220 OString
const & type
, OString
const & name
,
221 OString
const & descriptor
)
223 // invokevirtual <indexbyte1> <indexbyte2>:
224 appendU1(m_code
, 0xB6);
225 appendU2(m_code
, m_classFile
.addMethodrefInfo(type
, name
, descriptor
));
228 void ClassFile::Code::instrLookupswitch(
229 Code
const * defaultBlock
,
230 std::vector
< std::pair
< sal_Int32
, Code
* > > const & blocks
)
232 // lookupswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
233 // <defaultbyte4> <npairs1> <npairs2> <npairs3> <npairs4>
234 // <match--offset pairs...>:
235 std::vector
< std::pair
< sal_Int32
, Code
* > >::size_type size
= blocks
.size();
236 if (size
> SAL_MAX_INT32
) {
237 throw CannotDumpException("Lookup-switch too large for Java class file format");
239 Position pos1
= m_code
.size();
240 appendU1(m_code
, 0xAB);
241 int pad
= (pos1
+ 1) % 4;
242 for (int i
= 0; i
< pad
; ++i
) {
245 Position pos2
= pos1
+ 1 + pad
+ 8 + blocks
.size() * 8; //FIXME: overflow
246 appendU4(m_code
, static_cast< sal_uInt32
>(pos2
- pos1
)); //FIXME: overflow
247 pos2
+= defaultBlock
->m_code
.size(); //FIXME: overflow
248 appendU4(m_code
, static_cast< sal_uInt32
>(size
));
249 for (const std::pair
< sal_Int32
, Code
* >& pair
: blocks
)
251 appendU4(m_code
, static_cast< sal_uInt32
>(pair
.first
));
252 appendU4(m_code
, static_cast< sal_uInt32
>(pos2
- pos1
));
254 pos2
+= pair
.second
->m_code
.size(); //FIXME: overflow
256 appendStream(m_code
, defaultBlock
->m_code
);
257 for (const std::pair
< sal_Int32
, Code
* >& pair
: blocks
)
259 appendStream(m_code
, pair
.second
->m_code
);
263 void ClassFile::Code::instrNew(OString
const & type
) {
264 // new <indexbyte1> <indexbyte2>:
265 appendU1(m_code
, 0xBB);
266 appendU2(m_code
, m_classFile
.addClassInfo(type
));
269 void ClassFile::Code::instrNewarray(codemaker::UnoType::Sort sort
) {
271 sort
>= codemaker::UnoType::Sort::Boolean
272 && sort
<= codemaker::UnoType::Sort::Char
);
274 appendU1(m_code
, 0xBC);
275 static sal_uInt8
const atypes
[static_cast<int>(codemaker::UnoType::Sort::Char
)] = {
276 0x04, 0x08, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x06, 0x07, 0x05 };
277 appendU1(m_code
, atypes
[static_cast<int>(sort
) - 1]);
280 void ClassFile::Code::instrPop() {
282 appendU1(m_code
, 0x57);
285 void ClassFile::Code::instrPutfield(
286 OString
const & type
, OString
const & name
,
287 OString
const & descriptor
)
289 // putfield <indexbyte1> <indexbyte2>:
290 appendU1(m_code
, 0xB5);
291 appendU2(m_code
, m_classFile
.addFieldrefInfo(type
, name
, descriptor
));
294 void ClassFile::Code::instrPutstatic(
295 OString
const & type
, OString
const & name
,
296 OString
const & descriptor
)
298 // putstatic <indexbyte1> <indexbyte2>:
299 appendU1(m_code
, 0xB3);
300 appendU2(m_code
, m_classFile
.addFieldrefInfo(type
, name
, descriptor
));
303 void ClassFile::Code::instrReturn() {
305 appendU1(m_code
, 0xB1);
308 void ClassFile::Code::instrSwap() {
310 appendU1(m_code
, 0x5F);
313 void ClassFile::Code::instrTableswitch(
314 Code
const * defaultBlock
, sal_Int32 low
,
315 std::vector
< std::unique_ptr
<Code
> > const & blocks
)
317 // tableswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
318 // <defaultbyte4> <lowbyte1> <lowbyte2> <lowbyte3> <lowbyte4> <highbyte1>
319 // <highbyte2> <highbyte3> <highbyte4> <jump offsets...>:
320 Position pos1
= m_code
.size();
321 appendU1(m_code
, 0xAA);
322 int pad
= (pos1
+ 1) % 4;
323 for (int i
= 0; i
< pad
; ++i
) {
326 std::vector
< Code
* >::size_type size
= blocks
.size();
327 Position pos2
= pos1
+ 1 + pad
+ 12 + size
* 4; //FIXME: overflow
328 sal_uInt32 defaultOffset
= static_cast< sal_uInt32
>(pos2
- pos1
);
330 appendU4(m_code
, defaultOffset
);
331 pos2
+= defaultBlock
->m_code
.size(); //FIXME: overflow
332 appendU4(m_code
, static_cast< sal_uInt32
>(low
));
333 appendU4(m_code
, static_cast< sal_uInt32
>(low
+ (size
- 1)));
334 for (std::unique_ptr
<Code
> const & pCode
: blocks
)
336 if (pCode
== nullptr) {
337 appendU4(m_code
, defaultOffset
);
339 appendU4(m_code
, static_cast< sal_uInt32
>(pos2
- pos1
));
341 pos2
+= pCode
->m_code
.size(); //FIXME: overflow
344 appendStream(m_code
, defaultBlock
->m_code
);
345 for (std::unique_ptr
<Code
> const & pCode
: blocks
)
347 if (pCode
!= nullptr) {
348 appendStream(m_code
, pCode
->m_code
);
353 void ClassFile::Code::loadIntegerConstant(sal_Int32 value
) {
354 if (value
>= -1 && value
<= 5) {
356 appendU1(m_code
, static_cast< sal_uInt8
>(0x02 + value
+ 1));
357 } else if (value
>= -128 && value
<= 127) {
359 appendU1(m_code
, 0x10);
360 appendU1(m_code
, static_cast< sal_uInt8
>(value
));
361 } else if (value
>= -32768 && value
<= 32767) {
362 // sipush <byte1> <byte2>:
363 appendU1(m_code
, 0x11);
364 appendU2(m_code
, static_cast< sal_uInt16
>(value
));
366 ldc(m_classFile
.addIntegerInfo(value
));
370 void ClassFile::Code::loadStringConstant(OString
const & value
) {
371 ldc(m_classFile
.addStringInfo(value
));
374 void ClassFile::Code::loadLocalInteger(sal_uInt16 index
) {
375 accessLocal(index
, 0x1A, 0x15); // iload_<n>, iload
378 void ClassFile::Code::loadLocalLong(sal_uInt16 index
) {
379 accessLocal(index
, 0x1E, 0x16); // load_<n>, load
382 void ClassFile::Code::loadLocalFloat(sal_uInt16 index
) {
383 accessLocal(index
, 0x22, 0x17); // load_<n>, load
386 void ClassFile::Code::loadLocalDouble(sal_uInt16 index
) {
387 accessLocal(index
, 0x26, 0x18); // load_<n>, load
390 void ClassFile::Code::loadLocalReference(sal_uInt16 index
) {
391 accessLocal(index
, 0x2A, 0x19); // aload_<n>, aload
394 void ClassFile::Code::storeLocalReference(sal_uInt16 index
) {
395 accessLocal(index
, 0x4B, 0x3A); // astore_<n>, astore
398 void ClassFile::Code::branchHere(Branch branch
) {
399 std::vector
< unsigned char >::size_type n
= m_code
.size();
400 OSL_ASSERT(n
> branch
&& n
- branch
<= SAL_MAX_INT16
);
402 m_code
[branch
+ 1] = static_cast< sal_uInt8
>(n
>> 8);
403 m_code
[branch
+ 2] = static_cast< sal_uInt8
>(n
& 0xFF);
406 void ClassFile::Code::addException(
407 Position start
, Position end
, Position handler
, OString
const & type
)
409 OSL_ASSERT(start
< end
&& end
<= m_code
.size() && handler
<= m_code
.size());
410 if (m_exceptionTableLength
== SAL_MAX_UINT16
) {
411 throw CannotDumpException("Too many exception handlers for Java class file format");
413 ++m_exceptionTableLength
;
414 appendU2(m_exceptionTable
, static_cast< sal_uInt16
>(start
));
416 appendU2(m_exceptionTable
, static_cast< sal_uInt16
>(end
));
418 appendU2(m_exceptionTable
, static_cast< sal_uInt16
>(handler
));
420 appendU2(m_exceptionTable
, m_classFile
.addClassInfo(type
));
423 ClassFile::Code::Position
ClassFile::Code::getPosition() const {
424 return m_code
.size();
427 ClassFile::Code::Code(ClassFile
& classFile
)
428 : m_classFile(classFile
)
431 , m_exceptionTableLength(0)
434 void ClassFile::Code::ldc(sal_uInt16 index
) {
437 appendU1(m_code
, 0x12);
438 appendU1(m_code
, static_cast< sal_uInt8
>(index
));
440 // ldc_w <indexbyte1> <indexbyte2>:
441 appendU1(m_code
, 0x13);
442 appendU2(m_code
, index
);
446 void ClassFile::Code::accessLocal(
447 sal_uInt16 index
, sal_uInt8 fastOp
, sal_uInt8 normalOp
)
450 // ...load/store_<n>:
451 appendU1(m_code
, static_cast< sal_uInt8
>(fastOp
+ index
));
452 } else if (index
<= 0xFF) {
453 // ...load/store <index>:
454 appendU1(m_code
, normalOp
);
455 appendU1(m_code
, static_cast< sal_uInt8
>(index
));
457 // wide ...load/store <indexbyte1> <indexbyte2>:
458 appendU1(m_code
, 0xC4);
459 appendU1(m_code
, normalOp
);
460 appendU2(m_code
, index
);
464 ClassFile::ClassFile(
465 AccessFlags accessFlags
, OString
const & thisClass
,
466 OString
const & superClass
, OString
const & signature
):
467 m_constantPoolCount(1), m_accessFlags(accessFlags
), m_interfacesCount(0),
468 m_fieldsCount(0), m_methodsCount(0), m_attributesCount(0)
470 m_thisClass
= addClassInfo(thisClass
);
471 m_superClass
= addClassInfo(superClass
);
472 if (!signature
.isEmpty()) {
474 appendU2(m_attributes
, addUtf8Info("Signature"));
475 appendU4(m_attributes
, 2);
476 appendU2(m_attributes
, addUtf8Info(signature
));
480 ClassFile::~ClassFile() {}
482 ClassFile::Code
* ClassFile::newCode() {
483 return new Code(*this);
486 sal_uInt16
ClassFile::addIntegerInfo(sal_Int32 value
) {
487 std::map
< sal_Int32
, sal_uInt16
>::iterator
i(m_integerInfos
.find(value
));
488 if (i
!= m_integerInfos
.end()) {
491 sal_uInt16 index
= nextConstantPoolIndex(1);
492 appendU1(m_constantPool
, 3);
493 appendU4(m_constantPool
, static_cast< sal_uInt32
>(value
));
494 if (!m_integerInfos
.emplace(value
, index
).second
)
501 sal_uInt16
ClassFile::addFloatInfo(float value
) {
502 std::map
< float, sal_uInt16
>::iterator
i(m_floatInfos
.find(value
));
503 if (i
!= m_floatInfos
.end()) {
506 sal_uInt16 index
= nextConstantPoolIndex(1);
507 appendU1(m_constantPool
, 4);
508 union { float floatBytes
; sal_uInt32 uint32Bytes
; } bytes
;
509 bytes
.floatBytes
= value
;
510 appendU4(m_constantPool
, bytes
.uint32Bytes
);
511 if (!m_floatInfos
.emplace(value
, index
).second
)
518 sal_uInt16
ClassFile::addLongInfo(sal_Int64 value
) {
519 std::map
< sal_Int64
, sal_uInt16
>::iterator
i(m_longInfos
.find(value
));
520 if (i
!= m_longInfos
.end()) {
523 sal_uInt16 index
= nextConstantPoolIndex(2);
524 appendU1(m_constantPool
, 5);
525 appendU8(m_constantPool
, static_cast< sal_uInt64
>(value
));
526 if (!m_longInfos
.emplace(value
, index
).second
)
533 sal_uInt16
ClassFile::addDoubleInfo(double value
) {
534 std::map
< double, sal_uInt16
>::iterator
i(m_doubleInfos
.find(value
));
535 if (i
!= m_doubleInfos
.end()) {
538 sal_uInt16 index
= nextConstantPoolIndex(2);
539 appendU1(m_constantPool
, 6);
540 union { double doubleBytes
; sal_uInt64 uint64Bytes
; } bytes
;
541 bytes
.doubleBytes
= value
;
542 appendU8(m_constantPool
, bytes
.uint64Bytes
);
543 if (!m_doubleInfos
.emplace(value
, index
).second
)
550 void ClassFile::addInterface(OString
const & interface
) {
551 if (m_interfacesCount
== SAL_MAX_UINT16
) {
552 throw CannotDumpException("Too many interfaces for Java class file format");
555 appendU2(m_interfaces
, addClassInfo(interface
));
558 void ClassFile::addField(
559 AccessFlags accessFlags
, OString
const & name
,
560 OString
const & descriptor
, sal_uInt16 constantValueIndex
,
561 OString
const & signature
)
563 if (m_fieldsCount
== SAL_MAX_UINT16
) {
564 throw CannotDumpException("Too many fields for Java class file format");
567 appendU2(m_fields
, static_cast< sal_uInt16
>(accessFlags
));
568 appendU2(m_fields
, addUtf8Info(name
));
569 appendU2(m_fields
, addUtf8Info(descriptor
));
572 ((constantValueIndex
== 0 ? 0 : 1)
573 + (signature
.isEmpty() ? 0 : 1)));
574 if (constantValueIndex
!= 0) {
575 appendU2(m_fields
, addUtf8Info("ConstantValue"));
576 appendU4(m_fields
, 2);
577 appendU2(m_fields
, constantValueIndex
);
579 appendSignatureAttribute(m_fields
, signature
);
582 void ClassFile::addMethod(
583 AccessFlags accessFlags
, OString
const & name
,
584 OString
const & descriptor
, Code
const * code
,
585 std::vector
< OString
> const & exceptions
,
586 OString
const & signature
)
588 if (m_methodsCount
== SAL_MAX_UINT16
) {
589 throw CannotDumpException("Too many methods for Java class file format");
592 appendU2(m_methods
, static_cast< sal_uInt16
>(accessFlags
));
593 appendU2(m_methods
, addUtf8Info(name
));
594 appendU2(m_methods
, addUtf8Info(descriptor
));
595 std::vector
< OString
>::size_type excs
= exceptions
.size();
596 if (excs
> SAL_MAX_UINT16
) {
597 throw CannotDumpException("Too many exception specifications for Java class file format");
601 ((code
== nullptr ? 0 : 1) + (exceptions
.empty() ? 0 : 1)
602 + (signature
.isEmpty() ? 0 : 1)));
603 if (code
!= nullptr) {
604 std::vector
< unsigned char >::size_type codeSize
= code
->m_code
.size();
605 std::vector
< unsigned char >::size_type exceptionTableSize
606 = code
->m_exceptionTable
.size();
607 if (codeSize
> SAL_MAX_UINT32
- (2 + 2 + 4 + 2 + 2)
608 || (exceptionTableSize
609 > (SAL_MAX_UINT32
- (2 + 2 + 4 + 2 + 2)
610 - static_cast< sal_uInt32
>(codeSize
))))
612 throw CannotDumpException("Code block is too big for Java class file format");
614 appendU2(m_methods
, addUtf8Info("Code"));
617 (2 + 2 + 4 + static_cast< sal_uInt32
>(codeSize
) + 2
618 + static_cast< sal_uInt32
>(exceptionTableSize
) + 2));
619 appendU2(m_methods
, code
->m_maxStack
);
620 appendU2(m_methods
, code
->m_maxLocals
);
621 appendU4(m_methods
, static_cast< sal_uInt32
>(codeSize
));
622 appendStream(m_methods
, code
->m_code
);
623 appendU2(m_methods
, code
->m_exceptionTableLength
);
624 appendStream(m_methods
, code
->m_exceptionTable
);
625 appendU2(m_methods
, 0);
627 if (!exceptions
.empty()) {
628 appendU2(m_methods
, addUtf8Info("Exceptions"));
631 static_cast< sal_uInt32
>(2 + 2 * static_cast< sal_uInt32
>(excs
)));
632 appendU2(m_methods
, static_cast< sal_uInt16
>(excs
));
633 for (const OString
& ex
: exceptions
)
635 appendU2(m_methods
, addClassInfo(ex
));
638 appendSignatureAttribute(m_methods
, signature
);
641 void ClassFile::write(FileStream
& file
) const {
642 writeU4(file
, 0xCAFEBABE);
644 writeU2(file
, 49); // class file version of JRE 1.5
645 writeU2(file
, m_constantPoolCount
);
646 writeStream(file
, m_constantPool
);
647 writeU2(file
, static_cast< sal_uInt16
>(m_accessFlags
));
648 writeU2(file
, m_thisClass
);
649 writeU2(file
, m_superClass
);
650 writeU2(file
, m_interfacesCount
);
651 writeStream(file
, m_interfaces
);
652 writeU2(file
, m_fieldsCount
);
653 writeStream(file
, m_fields
);
654 writeU2(file
, m_methodsCount
);
655 writeStream(file
, m_methods
);
656 writeU2(file
, m_attributesCount
);
657 writeStream(file
, m_attributes
);
660 sal_uInt16
ClassFile::nextConstantPoolIndex(sal_uInt16 width
) {
661 OSL_ASSERT(width
== 1 || width
== 2);
662 if (m_constantPoolCount
> SAL_MAX_UINT16
- width
) {
663 throw CannotDumpException("Too many constant pool items for Java class file format");
665 sal_uInt16 index
= m_constantPoolCount
;
666 m_constantPoolCount
= m_constantPoolCount
+ width
;
670 sal_uInt16
ClassFile::addUtf8Info(OString
const & value
) {
671 std::map
< OString
, sal_uInt16
>::iterator
i(m_utf8Infos
.find(value
));
672 if (i
!= m_utf8Infos
.end()) {
675 if (value
.getLength() > SAL_MAX_UINT16
) {
676 throw CannotDumpException("UTF-8 string too long for Java class file format");
678 sal_uInt16 index
= nextConstantPoolIndex(1);
679 appendU1(m_constantPool
, 1);
680 appendU2(m_constantPool
, static_cast< sal_uInt16
>(value
.getLength()));
681 for (sal_Int32 j
= 0; j
< value
.getLength(); ++j
) {
682 appendU1(m_constantPool
, static_cast< sal_uInt8
>(value
[j
]));
684 if (!m_utf8Infos
.emplace(value
, index
).second
)
691 sal_uInt16
ClassFile::addClassInfo(OString
const & type
) {
692 sal_uInt16 nameIndex
= addUtf8Info(type
);
693 std::map
< sal_uInt16
, sal_uInt16
>::iterator
i(
694 m_classInfos
.find(nameIndex
));
695 if (i
!= m_classInfos
.end()) {
698 sal_uInt16 index
= nextConstantPoolIndex(1);
699 appendU1(m_constantPool
, 7);
700 appendU2(m_constantPool
, nameIndex
);
701 if (!m_classInfos
.emplace(nameIndex
, index
).second
)
708 sal_uInt16
ClassFile::addStringInfo(OString
const & value
) {
709 sal_uInt16 stringIndex
= addUtf8Info(value
);
710 std::map
< sal_uInt16
, sal_uInt16
>::iterator
i(
711 m_stringInfos
.find(stringIndex
));
712 if (i
!= m_stringInfos
.end()) {
715 sal_uInt16 index
= nextConstantPoolIndex(1);
716 appendU1(m_constantPool
, 8);
717 appendU2(m_constantPool
, stringIndex
);
718 if (!m_stringInfos
.emplace(stringIndex
, index
).second
)
725 sal_uInt16
ClassFile::addFieldrefInfo(
726 OString
const & type
, OString
const & name
,
727 OString
const & descriptor
)
729 sal_uInt16 classIndex
= addClassInfo(type
);
730 sal_uInt16 nameAndTypeIndex
= addNameAndTypeInfo(name
, descriptor
);
731 sal_uInt32 key
= (static_cast< sal_uInt32
>(classIndex
) << 16)
733 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(m_fieldrefInfos
.find(key
));
734 if (i
!= m_fieldrefInfos
.end()) {
737 sal_uInt16 index
= nextConstantPoolIndex(1);
738 appendU1(m_constantPool
, 9);
739 appendU2(m_constantPool
, classIndex
);
740 appendU2(m_constantPool
, nameAndTypeIndex
);
741 if (!m_fieldrefInfos
.emplace(key
, index
).second
)
748 sal_uInt16
ClassFile::addMethodrefInfo(
749 OString
const & type
, OString
const & name
,
750 OString
const & descriptor
)
752 sal_uInt16 classIndex
= addClassInfo(type
);
753 sal_uInt16 nameAndTypeIndex
= addNameAndTypeInfo(name
, descriptor
);
754 sal_uInt32 key
= (static_cast< sal_uInt32
>(classIndex
) << 16)
756 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(m_methodrefInfos
.find(key
));
757 if (i
!= m_methodrefInfos
.end()) {
760 sal_uInt16 index
= nextConstantPoolIndex(1);
761 appendU1(m_constantPool
, 10);
762 appendU2(m_constantPool
, classIndex
);
763 appendU2(m_constantPool
, nameAndTypeIndex
);
764 if (!m_methodrefInfos
.emplace(key
, index
).second
)
771 sal_uInt16
ClassFile::addInterfaceMethodrefInfo(
772 OString
const & type
, OString
const & name
,
773 OString
const & descriptor
)
775 sal_uInt16 classIndex
= addClassInfo(type
);
776 sal_uInt16 nameAndTypeIndex
= addNameAndTypeInfo(name
, descriptor
);
777 sal_uInt32 key
= (static_cast< sal_uInt32
>(classIndex
) << 16)
779 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(
780 m_interfaceMethodrefInfos
.find(key
));
781 if (i
!= m_interfaceMethodrefInfos
.end()) {
784 sal_uInt16 index
= nextConstantPoolIndex(1);
785 appendU1(m_constantPool
, 11);
786 appendU2(m_constantPool
, classIndex
);
787 appendU2(m_constantPool
, nameAndTypeIndex
);
788 if (!m_interfaceMethodrefInfos
.emplace(key
, index
).second
)
795 sal_uInt16
ClassFile::addNameAndTypeInfo(
796 OString
const & name
, OString
const & descriptor
)
798 sal_uInt16 nameIndex
= addUtf8Info(name
);
799 sal_uInt16 descriptorIndex
= addUtf8Info(descriptor
);
800 sal_uInt32 key
= (static_cast< sal_uInt32
>(nameIndex
) << 16)
802 std::map
< sal_uInt32
, sal_uInt16
>::iterator
i(
803 m_nameAndTypeInfos
.find(key
));
804 if (i
!= m_nameAndTypeInfos
.end()) {
807 sal_uInt16 index
= nextConstantPoolIndex(1);
808 appendU1(m_constantPool
, 12);
809 appendU2(m_constantPool
, nameIndex
);
810 appendU2(m_constantPool
, descriptorIndex
);
811 if (!m_nameAndTypeInfos
.emplace(key
, index
).second
)
818 void ClassFile::appendSignatureAttribute(
819 std::vector
< unsigned char > & stream
, OString
const & signature
)
821 if (!signature
.isEmpty()) {
822 appendU2(stream
, addUtf8Info("Signature"));
824 appendU2(stream
, addUtf8Info(signature
));
828 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */