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