1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * Operations on an Object.
19 */
20 #include "Dalvik.h"
21
22 /*
23 * Find a matching field, in the current class only.
24 *
25 * Returns NULL if the field can't be found. (Does not throw an exception.)
26 */
dvmFindInstanceField(const ClassObject * clazz,const char * fieldName,const char * signature)27 InstField* dvmFindInstanceField(const ClassObject* clazz,
28 const char* fieldName, const char* signature)
29 {
30 InstField* pField;
31 int i;
32
33 assert(clazz != NULL);
34
35 /*
36 * Find a field with a matching name and signature. The Java programming
37 * language does not allow you to have two fields with the same name
38 * and different types, but the Java VM spec does allow it, so we can't
39 * bail out early when the name matches.
40 */
41 pField = clazz->ifields;
42 for (i = 0; i < clazz->ifieldCount; i++, pField++) {
43 if (strcmp(fieldName, pField->name) == 0 &&
44 strcmp(signature, pField->signature) == 0)
45 {
46 return pField;
47 }
48 }
49
50 return NULL;
51 }
52
53 /*
54 * Find a matching field, in this class or a superclass.
55 *
56 * Searching through interfaces isn't necessary, because interface fields
57 * are inherently public/static/final.
58 *
59 * Returns NULL if the field can't be found. (Does not throw an exception.)
60 */
dvmFindInstanceFieldHier(const ClassObject * clazz,const char * fieldName,const char * signature)61 InstField* dvmFindInstanceFieldHier(const ClassObject* clazz,
62 const char* fieldName, const char* signature)
63 {
64 InstField* pField;
65
66 /*
67 * Search for a match in the current class.
68 */
69 pField = dvmFindInstanceField(clazz, fieldName, signature);
70 if (pField != NULL)
71 return pField;
72
73 if (clazz->super != NULL)
74 return dvmFindInstanceFieldHier(clazz->super, fieldName, signature);
75 else
76 return NULL;
77 }
78
79
80 /*
81 * Find a matching field, in this class or an interface.
82 *
83 * Returns NULL if the field can't be found. (Does not throw an exception.)
84 */
dvmFindStaticField(const ClassObject * clazz,const char * fieldName,const char * signature)85 StaticField* dvmFindStaticField(const ClassObject* clazz,
86 const char* fieldName, const char* signature)
87 {
88 const StaticField* pField;
89 int i;
90
91 assert(clazz != NULL);
92
93 /*
94 * Find a field with a matching name and signature. As with instance
95 * fields, the VM allows you to have two fields with the same name so
96 * long as they have different types.
97 */
98 pField = &clazz->sfields[0];
99 for (i = 0; i < clazz->sfieldCount; i++, pField++) {
100 if (strcmp(fieldName, pField->name) == 0 &&
101 strcmp(signature, pField->signature) == 0)
102 {
103 return (StaticField*) pField;
104 }
105 }
106
107 return NULL;
108 }
109
110 /*
111 * Find a matching field, in this class or a superclass.
112 *
113 * Returns NULL if the field can't be found. (Does not throw an exception.)
114 */
dvmFindStaticFieldHier(const ClassObject * clazz,const char * fieldName,const char * signature)115 StaticField* dvmFindStaticFieldHier(const ClassObject* clazz,
116 const char* fieldName, const char* signature)
117 {
118 StaticField* pField;
119
120 /*
121 * Search for a match in the current class.
122 */
123 pField = dvmFindStaticField(clazz, fieldName, signature);
124 if (pField != NULL)
125 return pField;
126
127 /*
128 * See if it's in any of our interfaces. We don't check interfaces
129 * inherited from the superclass yet.
130 *
131 * (Note the set may have been stripped down because of redundancy with
132 * the superclass; see notes in createIftable.)
133 */
134 int i = 0;
135 if (clazz->super != NULL) {
136 assert(clazz->iftableCount >= clazz->super->iftableCount);
137 i = clazz->super->iftableCount;
138 }
139 for ( ; i < clazz->iftableCount; i++) {
140 ClassObject* iface = clazz->iftable[i].clazz;
141 pField = dvmFindStaticField(iface, fieldName, signature);
142 if (pField != NULL)
143 return pField;
144 }
145
146 if (clazz->super != NULL)
147 return dvmFindStaticFieldHier(clazz->super, fieldName, signature);
148 else
149 return NULL;
150 }
151
152 /*
153 * Find a matching field, in this class or a superclass.
154 *
155 * We scan both the static and instance field lists in the class. If it's
156 * not found there, we check the direct interfaces, and then recursively
157 * scan the superclasses. This is the order prescribed in the VM spec
158 * (v2 5.4.3.2).
159 *
160 * In most cases we know that we're looking for either a static or an
161 * instance field and there's no value in searching through both types.
162 * During verification we need to recognize and reject certain unusual
163 * situations, and we won't see them unless we walk the lists this way.
164 */
dvmFindFieldHier(const ClassObject * clazz,const char * fieldName,const char * signature)165 Field* dvmFindFieldHier(const ClassObject* clazz, const char* fieldName,
166 const char* signature)
167 {
168 Field* pField;
169
170 /*
171 * Search for a match in the current class. Which set we scan first
172 * doesn't really matter.
173 */
174 pField = (Field*) dvmFindStaticField(clazz, fieldName, signature);
175 if (pField != NULL)
176 return pField;
177 pField = (Field*) dvmFindInstanceField(clazz, fieldName, signature);
178 if (pField != NULL)
179 return pField;
180
181 /*
182 * See if it's in any of our interfaces. We don't check interfaces
183 * inherited from the superclass yet.
184 */
185 int i = 0;
186 if (clazz->super != NULL) {
187 assert(clazz->iftableCount >= clazz->super->iftableCount);
188 i = clazz->super->iftableCount;
189 }
190 for ( ; i < clazz->iftableCount; i++) {
191 ClassObject* iface = clazz->iftable[i].clazz;
192 pField = (Field*) dvmFindStaticField(iface, fieldName, signature);
193 if (pField != NULL)
194 return pField;
195 }
196
197 if (clazz->super != NULL)
198 return dvmFindFieldHier(clazz->super, fieldName, signature);
199 else
200 return NULL;
201 }
202
203
204 /*
205 * Compare the given name, return type, and argument types with the contents
206 * of the given method. This returns 0 if they are equal and non-zero if not.
207 */
compareMethodHelper(Method * method,const char * methodName,const char * returnType,size_t argCount,const char ** argTypes)208 static inline int compareMethodHelper(Method* method, const char* methodName,
209 const char* returnType, size_t argCount, const char** argTypes)
210 {
211 DexParameterIterator iterator;
212 const DexProto* proto;
213
214 if (strcmp(methodName, method->name) != 0) {
215 return 1;
216 }
217
218 proto = &method->prototype;
219
220 if (strcmp(returnType, dexProtoGetReturnType(proto)) != 0) {
221 return 1;
222 }
223
224 if (dexProtoGetParameterCount(proto) != argCount) {
225 return 1;
226 }
227
228 dexParameterIteratorInit(&iterator, proto);
229
230 for (/*argCount*/; argCount != 0; argCount--, argTypes++) {
231 const char* argType = *argTypes;
232 const char* paramType = dexParameterIteratorNextDescriptor(&iterator);
233
234 if (paramType == NULL) {
235 /* Param list ended early; no match */
236 break;
237 } else if (strcmp(argType, paramType) != 0) {
238 /* Types aren't the same; no match. */
239 break;
240 }
241 }
242
243 if (argCount == 0) {
244 /* We ran through all the given arguments... */
245 if (dexParameterIteratorNextDescriptor(&iterator) == NULL) {
246 /* ...and through all the method's arguments; success! */
247 return 0;
248 }
249 }
250
251 return 1;
252 }
253
254 /*
255 * Get the count of arguments in the given method descriptor string,
256 * and also find a pointer to the return type.
257 */
countArgsAndFindReturnType(const char * descriptor,const char ** pReturnType)258 static inline size_t countArgsAndFindReturnType(const char* descriptor,
259 const char** pReturnType)
260 {
261 size_t count = 0;
262 bool bogus = false;
263 bool done = false;
264
265 assert(*descriptor == '(');
266 descriptor++;
267
268 while (!done) {
269 switch (*descriptor) {
270 case 'B': case 'C': case 'D': case 'F':
271 case 'I': case 'J': case 'S': case 'Z': {
272 count++;
273 break;
274 }
275 case '[': {
276 do {
277 descriptor++;
278 } while (*descriptor == '[');
279 /*
280 * Don't increment count, as it will be taken care of
281 * by the next iteration. Also, decrement descriptor
282 * to compensate for the increment below the switch.
283 */
284 descriptor--;
285 break;
286 }
287 case 'L': {
288 do {
289 descriptor++;
290 } while ((*descriptor != ';') && (*descriptor != '\0'));
291 count++;
292 if (*descriptor == '\0') {
293 /* Bogus descriptor. */
294 done = true;
295 bogus = true;
296 }
297 break;
298 }
299 case ')': {
300 /*
301 * Note: The loop will exit after incrementing descriptor
302 * one more time, so it then points at the return type.
303 */
304 done = true;
305 break;
306 }
307 default: {
308 /* Bogus descriptor. */
309 done = true;
310 bogus = true;
311 break;
312 }
313 }
314
315 descriptor++;
316 }
317
318 if (bogus) {
319 *pReturnType = NULL;
320 return 0;
321 }
322
323 *pReturnType = descriptor;
324 return count;
325 }
326
327 /*
328 * Copy the argument types into the given array using the given buffer
329 * for the contents.
330 */
copyTypes(char * buffer,const char ** argTypes,size_t argCount,const char * descriptor)331 static inline void copyTypes(char* buffer, const char** argTypes,
332 size_t argCount, const char* descriptor)
333 {
334 size_t i;
335 char c;
336
337 /* Skip the '('. */
338 descriptor++;
339
340 for (i = 0; i < argCount; i++) {
341 argTypes[i] = buffer;
342
343 /* Copy all the array markers and one extra character. */
344 do {
345 c = *(descriptor++);
346 *(buffer++) = c;
347 } while (c == '[');
348
349 if (c == 'L') {
350 /* Copy the rest of a class name. */
351 do {
352 c = *(descriptor++);
353 *(buffer++) = c;
354 } while (c != ';');
355 }
356
357 *(buffer++) = '\0';
358 }
359 }
360
361 /*
362 * Look for a match in the given class. Returns the match if found
363 * or NULL if not.
364 */
findMethodInListByDescriptor(const ClassObject * clazz,bool findVirtual,bool isHier,const char * name,const char * descriptor)365 static Method* findMethodInListByDescriptor(const ClassObject* clazz,
366 bool findVirtual, bool isHier, const char* name, const char* descriptor)
367 {
368 const char* returnType;
369 size_t argCount = countArgsAndFindReturnType(descriptor, &returnType);
370
371 if (returnType == NULL) {
372 LOGW("Bogus method descriptor: %s", descriptor);
373 return NULL;
374 }
375
376 /*
377 * Make buffer big enough for all the argument type characters and
378 * one '\0' per argument. The "- 2" is because "returnType -
379 * descriptor" includes two parens.
380 */
381 char buffer[argCount + (returnType - descriptor) - 2];
382 const char* argTypes[argCount];
383
384 copyTypes(buffer, argTypes, argCount, descriptor);
385
386 while (clazz != NULL) {
387 Method* methods;
388 size_t methodCount;
389 size_t i;
390
391 if (findVirtual) {
392 methods = clazz->virtualMethods;
393 methodCount = clazz->virtualMethodCount;
394 } else {
395 methods = clazz->directMethods;
396 methodCount = clazz->directMethodCount;
397 }
398
399 for (i = 0; i < methodCount; i++) {
400 Method* method = &methods[i];
401 if (compareMethodHelper(method, name, returnType, argCount,
402 argTypes) == 0) {
403 return method;
404 }
405 }
406
407 if (! isHier) {
408 break;
409 }
410
411 clazz = clazz->super;
412 }
413
414 return NULL;
415 }
416
417 /*
418 * Look for a match in the given clazz. Returns the match if found
419 * or NULL if not.
420 *
421 * "wantedType" should be METHOD_VIRTUAL or METHOD_DIRECT to indicate the
422 * list to search through. If the match can come from either list, use
423 * MATCH_UNKNOWN to scan both.
424 */
findMethodInListByProto(const ClassObject * clazz,MethodType wantedType,bool isHier,const char * name,const DexProto * proto)425 static Method* findMethodInListByProto(const ClassObject* clazz,
426 MethodType wantedType, bool isHier, const char* name, const DexProto* proto)
427 {
428 while (clazz != NULL) {
429 int i;
430
431 /*
432 * Check the virtual and/or direct method lists.
433 */
434 if (wantedType == METHOD_VIRTUAL || wantedType == METHOD_UNKNOWN) {
435 for (i = 0; i < clazz->virtualMethodCount; i++) {
436 Method* method = &clazz->virtualMethods[i];
437 if (dvmCompareNameProtoAndMethod(name, proto, method) == 0) {
438 return method;
439 }
440 }
441 }
442 if (wantedType == METHOD_DIRECT || wantedType == METHOD_UNKNOWN) {
443 for (i = 0; i < clazz->directMethodCount; i++) {
444 Method* method = &clazz->directMethods[i];
445 if (dvmCompareNameProtoAndMethod(name, proto, method) == 0) {
446 return method;
447 }
448 }
449 }
450
451 if (! isHier) {
452 break;
453 }
454
455 clazz = clazz->super;
456 }
457
458 return NULL;
459 }
460
461 /*
462 * Find a "virtual" method in a class.
463 *
464 * Does not chase into the superclass.
465 *
466 * Returns NULL if the method can't be found. (Does not throw an exception.)
467 */
dvmFindVirtualMethodByDescriptor(const ClassObject * clazz,const char * methodName,const char * descriptor)468 Method* dvmFindVirtualMethodByDescriptor(const ClassObject* clazz,
469 const char* methodName, const char* descriptor)
470 {
471 return findMethodInListByDescriptor(clazz, true, false,
472 methodName, descriptor);
473
474 // TODO? - throw IncompatibleClassChangeError if a match is
475 // found in the directMethods list, rather than NotFoundError.
476 // Note we could have been called by dvmFindVirtualMethodHier though.
477 }
478
479
480 /*
481 * Find a "virtual" method in a class, knowing only the name. This is
482 * only useful in limited circumstances, e.g. when searching for a member
483 * of an annotation class.
484 *
485 * Does not chase into the superclass.
486 *
487 * Returns NULL if the method can't be found. (Does not throw an exception.)
488 */
dvmFindVirtualMethodByName(const ClassObject * clazz,const char * methodName)489 Method* dvmFindVirtualMethodByName(const ClassObject* clazz,
490 const char* methodName)
491 {
492 Method* methods = clazz->virtualMethods;
493 int methodCount = clazz->virtualMethodCount;
494 int i;
495
496 for (i = 0; i < methodCount; i++) {
497 if (strcmp(methods[i].name, methodName) == 0)
498 return &methods[i];
499 }
500
501 return NULL;
502 }
503
504 /*
505 * Find a "virtual" method in a class.
506 *
507 * Does not chase into the superclass.
508 *
509 * Returns NULL if the method can't be found. (Does not throw an exception.)
510 */
dvmFindVirtualMethod(const ClassObject * clazz,const char * methodName,const DexProto * proto)511 Method* dvmFindVirtualMethod(const ClassObject* clazz, const char* methodName,
512 const DexProto* proto)
513 {
514 return findMethodInListByProto(clazz, METHOD_VIRTUAL, false, methodName,
515 proto);
516 }
517
518 /*
519 * Find a "virtual" method in a class. If we don't find it, try the
520 * superclass. Does not examine interfaces.
521 *
522 * Returns NULL if the method can't be found. (Does not throw an exception.)
523 */
dvmFindVirtualMethodHierByDescriptor(const ClassObject * clazz,const char * methodName,const char * descriptor)524 Method* dvmFindVirtualMethodHierByDescriptor(const ClassObject* clazz,
525 const char* methodName, const char* descriptor)
526 {
527 return findMethodInListByDescriptor(clazz, true, true,
528 methodName, descriptor);
529 }
530
531 /*
532 * Find a "virtual" method in a class. If we don't find it, try the
533 * superclass. Does not examine interfaces.
534 *
535 * Returns NULL if the method can't be found. (Does not throw an exception.)
536 */
dvmFindVirtualMethodHier(const ClassObject * clazz,const char * methodName,const DexProto * proto)537 Method* dvmFindVirtualMethodHier(const ClassObject* clazz,
538 const char* methodName, const DexProto* proto)
539 {
540 return findMethodInListByProto(clazz, METHOD_VIRTUAL, true, methodName,
541 proto);
542 }
543
544 /*
545 * Find a method in an interface. Searches superinterfaces.
546 *
547 * Returns NULL if the method can't be found. (Does not throw an exception.)
548 */
dvmFindInterfaceMethodHierByDescriptor(const ClassObject * iface,const char * methodName,const char * descriptor)549 Method* dvmFindInterfaceMethodHierByDescriptor(const ClassObject* iface,
550 const char* methodName, const char* descriptor)
551 {
552 Method* resMethod = dvmFindVirtualMethodByDescriptor(iface,
553 methodName, descriptor);
554 if (resMethod == NULL) {
555 /* scan superinterfaces and superclass interfaces */
556 int i;
557 for (i = 0; i < iface->iftableCount; i++) {
558 resMethod = dvmFindVirtualMethodByDescriptor(iface->iftable[i].clazz,
559 methodName, descriptor);
560 if (resMethod != NULL)
561 break;
562 }
563 }
564 return resMethod;
565 }
566
567 /*
568 * Find a method in an interface. Searches superinterfaces.
569 *
570 * Returns NULL if the method can't be found. (Does not throw an exception.)
571 */
dvmFindInterfaceMethodHier(const ClassObject * iface,const char * methodName,const DexProto * proto)572 Method* dvmFindInterfaceMethodHier(const ClassObject* iface,
573 const char* methodName, const DexProto* proto)
574 {
575 Method* resMethod = dvmFindVirtualMethod(iface, methodName, proto);
576 if (resMethod == NULL) {
577 /* scan superinterfaces and superclass interfaces */
578 int i;
579 for (i = 0; i < iface->iftableCount; i++) {
580 resMethod = dvmFindVirtualMethod(iface->iftable[i].clazz,
581 methodName, proto);
582 if (resMethod != NULL)
583 break;
584 }
585 }
586 return resMethod;
587 }
588
589 /*
590 * Find a "direct" method (static, private, or "<*init>").
591 *
592 * Returns NULL if the method can't be found. (Does not throw an exception.)
593 */
dvmFindDirectMethodByDescriptor(const ClassObject * clazz,const char * methodName,const char * descriptor)594 Method* dvmFindDirectMethodByDescriptor(const ClassObject* clazz,
595 const char* methodName, const char* descriptor)
596 {
597 return findMethodInListByDescriptor(clazz, false, false,
598 methodName, descriptor);
599 }
600
601 /*
602 * Find a "direct" method. If we don't find it, try the superclass. This
603 * is only appropriate for static methods, but will work for all direct
604 * methods.
605 *
606 * Returns NULL if the method can't be found. (Does not throw an exception.)
607 */
dvmFindDirectMethodHierByDescriptor(const ClassObject * clazz,const char * methodName,const char * descriptor)608 Method* dvmFindDirectMethodHierByDescriptor(const ClassObject* clazz,
609 const char* methodName, const char* descriptor)
610 {
611 return findMethodInListByDescriptor(clazz, false, true,
612 methodName, descriptor);
613 }
614
615 /*
616 * Find a "direct" method (static or "<*init>").
617 *
618 * Returns NULL if the method can't be found. (Does not throw an exception.)
619 */
dvmFindDirectMethod(const ClassObject * clazz,const char * methodName,const DexProto * proto)620 Method* dvmFindDirectMethod(const ClassObject* clazz, const char* methodName,
621 const DexProto* proto)
622 {
623 return findMethodInListByProto(clazz, METHOD_DIRECT, false, methodName,
624 proto);
625 }
626
627 /*
628 * Find a "direct" method in a class. If we don't find it, try the
629 * superclass.
630 *
631 * Returns NULL if the method can't be found. (Does not throw an exception.)
632 */
dvmFindDirectMethodHier(const ClassObject * clazz,const char * methodName,const DexProto * proto)633 Method* dvmFindDirectMethodHier(const ClassObject* clazz,
634 const char* methodName, const DexProto* proto)
635 {
636 return findMethodInListByProto(clazz, METHOD_DIRECT, true, methodName,
637 proto);
638 }
639
640 /*
641 * Find a virtual or static method in a class. If we don't find it, try the
642 * superclass. This is compatible with the VM spec (v2 5.4.3.3) method
643 * search order, but it stops short of scanning through interfaces (which
644 * should be done after this function completes).
645 *
646 * In most cases we know that we're looking for either a static or an
647 * instance field and there's no value in searching through both types.
648 * During verification we need to recognize and reject certain unusual
649 * situations, and we won't see them unless we walk the lists this way.
650 *
651 * Returns NULL if the method can't be found. (Does not throw an exception.)
652 */
dvmFindMethodHier(const ClassObject * clazz,const char * methodName,const DexProto * proto)653 Method* dvmFindMethodHier(const ClassObject* clazz, const char* methodName,
654 const DexProto* proto)
655 {
656 return findMethodInListByProto(clazz, METHOD_UNKNOWN, true, methodName,
657 proto);
658 }
659
660
661 /*
662 * We have a method pointer for a method in "clazz", but it might be
663 * pointing to a method in a derived class. We want to find the actual entry
664 * from the class' vtable. If "clazz" is an interface, we have to do a
665 * little more digging.
666 *
667 * For "direct" methods (private / constructor), we just return the
668 * original Method.
669 *
670 * (This is used for reflection and JNI "call method" calls.)
671 */
dvmGetVirtualizedMethod(const ClassObject * clazz,const Method * meth)672 const Method* dvmGetVirtualizedMethod(const ClassObject* clazz,
673 const Method* meth)
674 {
675 Method* actualMeth;
676 int methodIndex;
677
678 if (dvmIsDirectMethod(meth)) {
679 /* no vtable entry for these */
680 assert(!dvmIsStaticMethod(meth));
681 return meth;
682 }
683
684 /*
685 * If the method was declared in an interface, we need to scan through
686 * the class' list of interfaces for it, and find the vtable index
687 * from that.
688 *
689 * TODO: use the interface cache.
690 */
691 if (dvmIsInterfaceClass(meth->clazz)) {
692 int i;
693
694 for (i = 0; i < clazz->iftableCount; i++) {
695 if (clazz->iftable[i].clazz == meth->clazz)
696 break;
697 }
698 if (i == clazz->iftableCount) {
699 dvmThrowIncompatibleClassChangeError(
700 "invoking method from interface not implemented by class");
701 return NULL;
702 }
703
704 methodIndex = clazz->iftable[i].methodIndexArray[meth->methodIndex];
705 } else {
706 methodIndex = meth->methodIndex;
707 }
708
709 assert(methodIndex >= 0 && methodIndex < clazz->vtableCount);
710 actualMeth = clazz->vtable[methodIndex];
711
712 /*
713 * Make sure there's code to execute.
714 */
715 if (dvmIsAbstractMethod(actualMeth)) {
716 dvmThrowAbstractMethodError(NULL);
717 return NULL;
718 }
719 assert(!dvmIsMirandaMethod(actualMeth));
720
721 return actualMeth;
722 }
723
724 /*
725 * Get the source file for a method.
726 */
dvmGetMethodSourceFile(const Method * meth)727 const char* dvmGetMethodSourceFile(const Method* meth)
728 {
729 /*
730 * TODO: A method's debug info can override the default source
731 * file for a class, so we should account for that possibility
732 * here.
733 */
734 return meth->clazz->sourceFile;
735 }
736
737 /*
738 * Dump some information about an object.
739 */
dvmDumpObject(const Object * obj)740 void dvmDumpObject(const Object* obj)
741 {
742 ClassObject* clazz;
743 int i;
744
745 if (obj == NULL || obj->clazz == NULL) {
746 LOGW("Null or malformed object not dumped");
747 return;
748 }
749
750 clazz = obj->clazz;
751 LOGD("----- Object dump: %p (%s, %d bytes) -----",
752 obj, clazz->descriptor, (int) clazz->objectSize);
753 //printHexDump(obj, clazz->objectSize);
754 LOGD(" Fields:");
755 while (clazz != NULL) {
756 LOGD(" -- %s", clazz->descriptor);
757 for (i = 0; i < clazz->ifieldCount; i++) {
758 const InstField* pField = &clazz->ifields[i];
759 char type = pField->signature[0];
760
761 if (type == 'F' || type == 'D') {
762 double dval;
763
764 if (type == 'F')
765 dval = dvmGetFieldFloat(obj, pField->byteOffset);
766 else
767 dval = dvmGetFieldDouble(obj, pField->byteOffset);
768
769 LOGD(" %2d: '%s' '%s' af=%04x off=%d %.3f", i,
770 pField->name, pField->signature,
771 pField->accessFlags, pField->byteOffset, dval);
772 } else {
773 u8 lval;
774
775 if (type == 'J')
776 lval = dvmGetFieldLong(obj, pField->byteOffset);
777 else if (type == 'Z')
778 lval = dvmGetFieldBoolean(obj, pField->byteOffset);
779 else
780 lval = dvmGetFieldInt(obj, pField->byteOffset);
781
782 LOGD(" %2d: '%s' '%s' af=%04x off=%d 0x%08llx", i,
783 pField->name, pField->signature,
784 pField->accessFlags, pField->byteOffset, lval);
785 }
786 }
787
788 clazz = clazz->super;
789 }
790 if (dvmIsClassObject(obj)) {
791 LOGD(" Static fields:");
792 const StaticField* sfields = &((ClassObject *)obj)->sfields[0];
793 for (i = 0; i < ((ClassObject *)obj)->sfieldCount; ++i) {
794 const StaticField* pField = &sfields[i];
795 size_t byteOffset = (size_t)pField - (size_t)sfields;
796 char type = pField->signature[0];
797
798 if (type == 'F' || type == 'D') {
799 double dval;
800
801 if (type == 'F')
802 dval = pField->value.f;
803 else
804 dval = pField->value.d;
805
806 LOGD(" %2d: '%s' '%s' af=%04x off=%zd %.3f", i,
807 pField->name, pField->signature,
808 pField->accessFlags, byteOffset, dval);
809 } else {
810 u8 lval;
811
812 if (type == 'J')
813 lval = pField->value.j;
814 else if (type == 'Z')
815 lval = pField->value.z;
816 else
817 lval = pField->value.i;
818
819 LOGD(" %2d: '%s' '%s' af=%04x off=%zd 0x%08llx", i,
820 pField->name, pField->signature,
821 pField->accessFlags, byteOffset, lval);
822 }
823 }
824 }
825 }
826