PDA

View Full Version : Nokia Object Oriented Model



yak
06-02-2006, 03:23 PM
Hi, since I've reversed the classes/objects system of DCT4 phones I would like to share the knowledge.



/*
Nokia Object Oriented Model
---------------------------

Such object oriented model can be found in most if not all DCT4 phones and also in 7110/6210 (DCT3).

Reversed by [Yak]
*/


typedef struct
{
Class *Class;
// Object's private data follow
} Object;

typedef struct
{
unsigned short ID;
unsigned (*Handler)(Object *This, unsigned short MethodID, unsigned Arg0, unsigned Arg1, unsigned Arg2);
} Method;

typedef struct
{
Class *Class;
Class *SuperClass;
Method *Methods; // table of methods, last one has ID == M_C_END
unsigned short MethodsCount;
unsigned short ObjectSize;
char *Name;
} Class;


/* calling methods on objects */
unsigned DoMethod(Object *O, unsigned short MethodID);
unsigned DoMethod1(Object *O, unsigned short MethodID, unsigned Arg0);
unsigned DoMethod2(Object *O, unsigned short MethodID, unsigned Arg0, unsigned Arg1);
unsigned DoMethod3(Object *O, unsigned short MethodID, unsigned Arg0, unsigned Arg1, unsigned Arg2);

/* calling methods of superclass; used in class methods handlers */
unsigned DoClassSuperMethod(Class *C, Obejct *O, unsigned short MethodID, unsigned Arg0, unsigned Arg1, unsigned Arg2);

#define M_IS_OF_CLASS (0xC000)
#define M_GET_METHOD_HANDLER (0xC001)
#define M_GET_CLASS (0xC002)
#define M_NEW (0xC003)
#define M_CONSTRUCTOR (0xC004)
#define M_DELETE (0xC005)
#define M_DESTRUCTOR (0xC006)

#define M_C_END (0x0000)
#define M_C_ANY (0xffff)

/*
M_IS_OF_CLASS
-------------

ret = DoMethod1(object, M_IS_OF_CLASS, class);

Checks if <object> is derived from specified <class>. Returns 1 if yes or 0 if no.


M_GET_METHOD_HANDLER
--------------------

handler = DoMethod1(object, M_GET_METHOD_HANDLER, method_id);

Returns the method handling function pointer for specified <method_id>. Returns
NULL if <object> doesn't support <method_id> method.


M_GET_CLASS
-----------

class = DoMethod(object, M_GET_CLASS);

Returns a pointer to <object>'s class.


M_NEW
-----

object = DoMethod(former, M_NEW);
object = DoMethod1(former, M_NEW, space);
object = DoMethod2(former, M_NEW, space, arg1);
object = DoMethod3(former, M_NEW, space, arg1, arg2);

Creates a new object and returns a pointer to it. The <former> can be either an
already existing object of some class or directly a class pointer. If <space>
is specified and not NULL, no memory is allocated, instead, the object is
created at the address specified by <space> (be sure to have enough space there).
After creating, M_CONSTRUCTOR method is called. All the arguments are passed to it.


M_CONSTRUCTOR
-------------

DoMethod(object, M_CONSTRUCTOR);
DoMethod1(object, M_CONSTRUCTOR, arg0);
DoMethod2(object, M_CONSTRUCTOR, arg0, arg1);
DoMethod3(object, M_CONSTRUCTOR, arg0, arg1, arg2);

Initializes an object. If called from M_NEW received its <space> argument as
<arg0>.


M_DELETE
--------

DoMethod(object, M_DELETE);

Deletes an object. However, before it is done, M_DESTRUCTOR is called to
deinitialize the object (free its all resources).


M_DESTRUCTOR
------------

DoMethod(object, M_DESTRUCTOR);

Deinitializes an object.


M_C_END
-------

Special ID used to mark the end of methods table in a class.


M_C_ANY
-------

Special ID used to mark a method in methods table of a class. Such a method will
be called for any method called on the object.

*/

/*
Addresses:

DoMethod() .............: 8310 v6.20 at 0x12cec02
DoMethod1() ............: 8310 v6.20 at 0x12cebdc
DoMethod2() ............: 8310 v6.20 at 0x12cebb4
DoMethod3() ............: 8310 v6.20 at 0x12ceb8c

DoClassSuperMethod() ...: 8310 v6.20 at 0x12cec24

Object (abstract) ......: root class, all other are subclasses of this one.
8310 v6.20 at 0x14e215c
*/

Pointers are for 8310 but I've also found all this in 3100 and 5140i.

In the attachment you will find a tree of classes in 8310 v6.20. The ZIP'ed one contains a complete tree with all the methods and class references found in the code.

Happy reversing.
[Yak]

nok5rev
08-02-2006, 03:42 PM
Very nice info. It will surely help reversing a lot.

It would be interesting to see if the method IDs are consistend between phone models, so that knowledge from a phone could be applied to others.

krisha
20-02-2006, 04:15 AM
nice information.

on 3100 unfortunately the class names are removed, but if the MessageIDs are the same, we can convert it :-)

spaceimpact33
02-03-2006, 05:45 AM
Woah verry impressive!
Looks like I am going to have to learn C++ now lol.

Thanks for sharing this with us all =D.

Hexxx
03-03-2006, 04:47 PM
Looks like you came close to java :)

I want to share what i know.

There's an interface table of java classes it looks like:
RAM0:000E369C javax_microedition_midlet_MIDletStateChangeException DCD java_lang_Class ; BaseInterface.field_0
RAM0:000E369C ; DATA XREF: ROM:014F08D8o
RAM0:000E369C ; ROM:014F08F8o ...
RAM0:000E369C DCD 0 ; BaseInterface.field_4
RAM0:000E369C DCD javax_microedition_midlet; BaseInterface.pClassCollectionName
RAM0:000E369C DCD cMIDletStateChangeException; BaseInterface.pClassName
RAM0:000E369C DCD off_E3AEC ; BaseInterface.field_10
RAM0:000E369C DCW 0x6021 ; BaseInterface.flags
RAM0:000E369C DCW 0x18D ; BaseInterface.field_16
RAM0:000E369C DCD java_lang_Exception ; BaseInterface.pBaseClass
RAM0:000E369C DCD MIDletStateChangeException_Impl; BaseInterface.pClassImplementation
RAM0:000E369C DCD 0 ; BaseInterface.pFieldDescriptorTable
RAM0:000E369C DCD MIDletStateChangeException_MT; BaseInterface.pMethodDesctiptorTable
RAM0:000E369C DCD 0 ; field_28
RAM0:000E369C DCD 0 ; field_2C
RAM0:000E369C DCW 2 ; field_30
RAM0:000E369C DCW 5 ; field_32
RAM0:000E369C DCD 0 ; field_34


RAM0:000E36D4 com_nokia_mid_impl_isa_io_protocol_external_MessageEventConsumer DCD java_lang_Class ; BaseInterface.field_0
RAM0:000E36D4 ; DATA XREF: ROM:com_nokia_mid_impl_isa_io_protocol_external_MessageEventConsumer___init_o
RAM0:000E36D4 ; ROM:com_nokia_mid_impl_isa_io_protocol_external_MessageEventConsumer__instanceo ...
RAM0:000E36D4 DCD 0 ; BaseInterface.field_4
RAM0:000E36D4 DCD com_nokia_mid_impl_isa_io_protocol_external; BaseInterface.pClassCollectionName
RAM0:000E36D4 DCD MessageEventConsumer; BaseInterface.pClassName
RAM0:000E36D4 DCD com_sun_cldc_i18n_uclc_DefaultCaseConverter; BaseInterface.field_10
RAM0:000E36D4 DCW 0x2031 ; BaseInterface.flags
RAM0:000E36D4 DCW 0x170 ; BaseInterface.field_16
RAM0:000E36D4 DCD java_lang_Object ; BaseInterface.pBaseClass
RAM0:000E36D4 DCD MessageEventConsumer_Impl; BaseInterface.pClassImplementation
RAM0:000E36D4 DCD MessageEventConsumer_FT; BaseInterface.pFieldDescriptorTable
RAM0:000E36D4 DCD MessageEventConsumer_MT; BaseInterface.pMethodDesctiptorTable
RAM0:000E36D4 DCD unk_150267E ; field_28
RAM0:000E36D4 DCD 0 ; field_2C
RAM0:000E36D4 DCW 0 ; field_30
RAM0:000E36D4 DCW 4 ; field_32
RAM0:000E36D4 DCD 0 ; field_34

and so on. This table can be found in rom, but it reallity, it is somehow copied to RAM.

I've almost finished reconstruction of Interface descriptor:
00000000 BaseInterfaceDescriptor struc ; (sizeof=0x28)
00000000 pClass DCD ? ; offset
00000004 field_4 DCD ?
00000008 pClassCollectionName DCD ? ; offset
0000000C pClassName DCD ? ; offset
00000010 pClass2 DCD ? ; offset
00000014 flags DCW ?
00000016 field_16 DCW ?
00000018 pBaseClass DCD ? ; offset
0000001C pClassImplementation DCD ? ; offset
00000020 pFieldDescriptorTable DCD ? ; offset
00000024 pMethodDesctiptorTable DCD ? ; offset
00000028 BaseInterfaceDescriptor ends
00000028
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 InterfaceDescriptor struc ; (sizeof=0x38)
00000000 BaseInterface BaseInterfaceDescriptor ?
00000028 field_28 DCD ? ; offset
0000002C field_2C DCD ?
00000030 field_30 DCW ?
00000032 field_32 DCW ?
00000034 field_34 DCD ?
00000038 InterfaceDescriptor ends

pClassCollectionName and pClassName point to MethodNameDescriptor structure:
00000000 MethodNameDescriptor struc ; (sizeof=0x8)
00000000 pNextDescriptor DCD ? ; offset
00000004 NameLength DCW ?
00000006 MethodID DCW ?
00000008 MethodNameDescriptor ends

so, for RAM0:000E369C DCD javax_microedition_midlet; it points to:
ROM:014BFA78 javax_microedition_midlet DCD off_14BE560 ; pNextDescriptor
ROM:014BFA78 ; DATA XREF: RAM0:javax_microedition_midlet_MIDletStateChangeExceptiono
ROM:014BFA78 ; RAM0:stru_E3D8Co ...
ROM:014BFA78 DCW 0x19 ; NameLength
ROM:014BFA78 DCW 0x639 ; MethodID
ROM:014BFA80 aJavaxMicroeditionMidlet DCB "javax/microedition/midlet",0

and for RAM0:000E369C DCD cMIDletStateChangeException:
ROM:014BB3FC cMIDletStateChangeException DCD unk_14B9EB8 ; pNextDescriptor
ROM:014BB3FC ; DATA XREF: RAM0:javax_microedition_midlet_MIDletStateChangeExceptiono
ROM:014BB3FC ; ROM:cMIDletAccesso ...
ROM:014BB3FC DCW 0x1A ; NameLength
ROM:014BB3FC DCW 0x2FD ; MethodID
ROM:014BB404 aMidletstatechangeexception DCB "MIDletStateChangeException",0

There are more interesting fields in BaseInterfaceDescriptor:
1) pClassImplementation - pointer to some kind of Class Descriptor. It's an array of offsets to the method descriptors, field descriptors and some unknown structures.
2) pFieldDescriptorTable - pointer to the array of field descriptors
3) pMethodDesctiptorTable - pointer to the array of method descriptors

both ClassImplementation, FieldDescriptorTable and MethodDesctiptorTable starts with dword that contain the number of methods/fields in the table.

00000000 FieldDescriptor struc ; (sizeof=0x10)
00000000 FieldNameID DCW ? ; enum ConstantTable
00000002 field_2 DCW ?
00000004 flags DCD ? ; enum ConstDesriptorFlags
00000008 pInterfaceDescriptor DCD ? ; offset
0000000C PValueOrValue DCD ? ; offset
00000010 FieldDescriptor ends

the field FieldNameID of FieldDescriptor is an ID that can be found at MethodNameDescriptor, so you can easily find the name for the method/field by its ID.

00000000 MethodDescriptor struc ; (sizeof=0x20)
00000000 MethodID DCW ? ; enum ConstantTable
00000002 ClassID DCW ? ; base 16
00000004 pFunction DCD ? ; offset
00000008 field_8 DCD ? ; offset
0000000C field_C DCD ? ; offset
00000010 field_10 DCW ?
00000012 field_12 DCW ?
00000014 flags DCD ? ; enum ConstDesriptorFlags
00000018 pInterfaceDescriptor DCD ? ; offset
0000001C field_1C DCW ?
0000001E ArgumentCount DCW ?
00000020 MethodDescriptor ends

MethodID is the same as FieldNameID in MethodDescriptor; pFunction - a pointer to function, depending on flags it can point to java or to native (thumb) function.

The flags are:
00000001 ; enum ConstDesriptorFlags (bitfield)
00000001 ACC_PUBLIC EQU 1
00000002 ACC_PRIVATE EQU 2
00000004 ACC_PROTECTED EQU 4
00000008 ACC_STATIC EQU 8
00000010 ACC_FINAL EQU 0x10
00000020 ACC_SYNCHRONIZED EQU 0x20
00000040 ACC_VOLATILE EQU 0x40
00000080 ACC_TRANSIENT EQU 0x80
00000100 ACC_NATIVE EQU 0x100
00000400 ACC_ABSTRACT EQU 0x400
00000800 ACC_STRICT EQU 0x800
00008000 ACC_WRITE EQU 0x8000

krisha
07-03-2006, 02:55 PM
It would be interesting to see if the method IDs are consistend between phone models, so that knowledge from a phone could be applied to others.

method IDs are the same on 3100 and 8310, some changed or new are added but many remain the same :)

it's also possible to find objects with the class signature