8 #include <sys/socket.h>
9 #include <netinet/in.h>
10 #include <arpa/inet.h>
17 #include <barry/endian.h>
18 #include <barry/barry.h>
28 using namespace Barry
;
34 static void * acceptWrapper(void *data
);
37 JDWServer::JDWServer(const char *address
, int port
)
42 this->address
= strdup(address
);
44 this->printConsoleMessage
= NULL
;
46 searchDebugFile(debugFileList
);
50 JDWServer::~JDWServer()
58 void JDWServer::setDevice(Barry::Mode::JVMDebug
*device
)
64 void JDWServer::setPasswordDevice(string password
)
66 this->password
= password
;
70 void JDWServer::setConsoleCallback(void (*callback
)(string message
))
72 printConsoleMessage
= callback
;
76 bool JDWServer::start()
81 struct sockaddr_in sad
;
84 memset((char *) &sad
, '\0', sizeof(struct sockaddr_in
));
87 sad
.sin_addr
.s_addr
= INADDR_ANY
;
89 sad
.sin_addr
.s_addr
= inet_addr(address
);
91 if (sad
.sin_addr
.s_addr
== INADDR_NONE
) {
92 hp
= gethostbyname(address
);
100 memcpy((char*) &sad
.sin_addr
, (char*) hp
->h_addr
, (size_t) hp
->h_length
);
104 sad
.sin_family
= AF_INET
;
105 sad
.sin_port
= htons((short) (port
& 0xFFFF));
108 sockfd
= socket(sad
.sin_family
, SOCK_STREAM
, 0);
117 rc
= bind(sockfd
, (struct sockaddr
*) &sad
, sizeof(sad
));
129 if (listen(sockfd
, SOMAXCONN
) < 0) {
138 handler
= new JDWHandler(sockfd
, acceptWrapper
, (void*) this);
144 static void * acceptWrapper(void *data
) {
147 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
149 s
= (JDWServer
*) data
;
152 s
->acceptConnection();
159 s
->detachFromDevice();
167 void JDWServer::acceptConnection() {
171 struct sockaddr_in addr
;
173 sa
= (struct sockaddr
*) &addr
;
175 addrlen
= sizeof(addr
);
177 fd
= accept(sockfd
, sa
, &addrlen
);
179 fcntl(fd
, F_SETFL
, O_NONBLOCK
);
186 void JDWServer::attachToDevice() {
189 targetrunning
= false;
191 jvmdebug
->Open(password
.c_str());
194 jvmdebug
->Unknown01();
195 jvmdebug
->Unknown02();
196 jvmdebug
->Unknown03();
197 jvmdebug
->Unknown04();
198 jvmdebug
->Unknown05();
200 jvmdebug
->GetModulesList(modulesList
);
203 // Check debug info for each modules
204 vector
<JVMModulesEntry
>::iterator b
= modulesList
.begin();
205 for ( ; b
!= modulesList
.end(); b
++) {
208 JVMModulesEntry entry
= *b
;
210 ret
= loadDebugInfo(debugFileList
, entry
.UniqueID
, entry
.Name
, codInfo
);
213 appList
[entry
.UniqueID
].load(codInfo
);
216 cout
<< "No debug information found for '" << entry
.Name
;
217 cout
<< "' (" << hex
<< setfill('0') << setw(8) << entry
.UniqueID
<< ")." << endl
;
223 void JDWServer::detachFromDevice() {
229 #define JDWP_HELLO_STRING "JDWP-Handshake"
233 bool JDWServer::hello() {
236 Barry::Data response
;
238 const size_t len
= strlen(JDWP_HELLO_STRING
);
243 ret
= msg
.Receive(response
);
247 int size
= response
.GetSize();
248 char *str
= (char *) response
.GetBuffer();
253 if (!strncmp(str
, JDWP_HELLO_STRING
, len
)) {
254 Data
command(JDWP_HELLO_STRING
, len
);
265 void JDWServer::run() {
271 MAKE_JDWPPACKET(rpack
, command
);
277 // Read JDWP message from device
278 int value
= jvmdebug
->GetConsoleMessage(str
);
284 ret
= jvmdebug
->GetStatus(status
);
287 // Read JDB message from host
288 msg
.Receive(command
);
290 if (command
.GetSize() > 0) {
292 rpack
= (const Protocol::Packet
*) command
.GetData();
294 if (command
.GetSize() != be_btohl(rpack
->length
)) {
295 cout
<< "Packet size error !!!" << endl
;
297 // TODO : add throw exception
302 CommandsetProcess(command
);
307 ret
= jvmdebug
->WaitStatus(status
);
311 if (printConsoleMessage
!= NULL
)
312 printConsoleMessage(str
);
316 // Read JDB message from host
317 msg
.Receive(command
);
319 if (command
.GetSize() > 0) {
321 rpack
= (const Protocol::Packet
*) command
.GetData();
323 if (command
.GetSize() != be_btohl(rpack
->length
)) {
324 cout
<< "Packet size error !!!" << endl
;
326 // TODO : add throw exception
331 CommandsetProcess(command
);
340 bool JDWServer::stop() {
355 void JDWServer::CommandsetProcess(Data
&cmd
) {
356 MAKE_JDWPPACKET(rpack
, cmd
);
358 switch (rpack
->u
.command
.commandset
) {
359 case JDWP_CMDSET_VIRTUALMACHINE
:
360 CommandsetVirtualMachineProcess(cmd
);
363 case JDWP_CMDSET_REFERECENTYPE
:
366 case JDWP_CMDSET_CLASSTYPE
:
369 case JDWP_CMDSET_ARRAYTYPE
:
372 case JDWP_CMDSET_INTERFACETYPE
:
375 case JDWP_CMDSET_METHOD
:
378 case JDWP_CMDSET_FIELD
:
381 case JDWP_CMDSET_OBJECTREFERENCE
:
384 case JDWP_CMDSET_STRINGREFERENCE
:
387 case JDWP_CMDSET_THREADREFERENCE
:
390 case JDWP_CMDSET_THREADGROUPREFERENCE
:
393 case JDWP_CMDSET_ARRAYREFERENCE
:
396 case JDWP_CMDSET_CLASSLOADERREFERENCE
:
399 case JDWP_CMDSET_EVENTREQUEST
:
400 CommandsetEventRequestProcess(cmd
);
403 case JDWP_CMDSET_STACKFRAME
:
406 case JDWP_CMDSET_CLASSOBJECTREFERENCE
:
409 case JDWP_CMDSET_EVENT
:
413 // TODO : add exception (or alert)
414 cout
<< "Commandset unknown !!!" << endl
;
419 void JDWServer::CommandsetVirtualMachineProcess(Data
&cmd
) {
422 MAKE_JDWPPACKET(rpack
, cmd
);
424 switch (rpack
->u
.command
.command
) {
425 case JDWP_CMD_VERSION
:
429 case JDWP_CMD_ALLCLASSES
:
430 CommandAllClasses(cmd
);
433 case JDWP_CMD_ALLTHREADS
:
434 CommandAllThreads(cmd
);
437 case JDWP_CMD_DISPOSE
:
439 targetrunning
= false;
443 case JDWP_CMD_IDSIZES
:
447 case JDWP_CMD_SUSPEND
:
449 targetrunning
= false;
452 case JDWP_CMD_RESUME
:
454 targetrunning
= true;
457 case JDWP_CMD_CLASSPATHS
:
458 CommandClassPaths(cmd
);
464 void JDWServer::CommandsetEventRequestProcess(Data
&cmd
) {
467 MAKE_JDWPPACKET(rpack
, cmd
);
469 switch (rpack
->u
.command
.command
) {
477 void JDWServer::CommandVersion(Data
&cmd
) {
483 size_t offset
= JDWP_PACKET_HEADER_SIZE
+ JDWP_RESPONSE_HEADER_SIZE
;
485 AddDataString(response
, offset
, string("RIM JVM"));
486 AddDataInt(response
, offset
, be_htobl(1));
487 AddDataInt(response
, offset
, be_htobl(4));
488 AddDataString(response
, offset
, string("1.4"));
489 AddDataString(response
, offset
, string("RIM JVM"));
491 response
.ReleaseBuffer(offset
);
494 size_t total_size
= response
.GetSize();
496 // Fill in the header values
497 MAKE_JDWPPACKETPTR_BUF(cpack
, response
.GetBuffer(total_size
));
498 Protocol::Packet
&packet
= *cpack
;
501 MAKE_JDWPPACKET(rpack
, cmd
);
503 packet
.length
= be_htobl(total_size
);
504 packet
.id
= rpack
->id
;
506 packet
.u
.response
.errorcode
= be_htobs(0);
508 response
.ReleaseBuffer(total_size
);
513 //struct ClassesFormat {
514 // uint8_t refTypeTag;
516 // const char *signature;
519 // struct ClassesFormat myClasses[] = {
520 // { 0x01, 0x01, "Lcom/rim/resources/net_rim_rimsecuridlibRIMResources;", 0x04 },
521 // { 0x01, 0x02, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimDatabaseFullException;", 0x04 },
522 // { 0x01, 0x03, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimDecryptFailException;", 0x04 },
523 // { 0x01, 0x04, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimDuplicateNameException;", 0x04 },
524 // { 0x01, 0x05, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimDuplicateTokenException;", 0x04 },
525 // { 0x01, 0x06, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimInvalidParamException;", 0x04 },
526 // { 0x01, 0x07, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimSecurIDLib;", 0x04 },
527 // { 0x01, 0x08, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimWrongDeviceIDException;", 0x04 },
528 // { 0x01, 0x09, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimWrongFormFactorException;", 0x04 },
533 void JDWServer::CommandAllClasses(Data
&cmd
) {
541 size_t offset
= JDWP_PACKET_HEADER_SIZE
+ JDWP_RESPONSE_HEADER_SIZE
;
543 // Count and index the class (start to '1')
545 map
<uint32_t, JDWAppInfo
>::iterator it
;
547 for (it
= appList
.begin(); it
!= appList
.end(); it
++) {
548 JDWAppInfo
*appInfo
= &(it
->second
);
549 JDGClassList
*list
= &(appInfo
->classList
);
551 vector
<JDGClassEntry
>::iterator b
;
553 for (b
= list
->begin(); b
!= list
->end(); b
++) {
555 // I don't from class field, we have to filter the class view by JDB
556 if (b
->type
!= 0x824)
563 // Add '9' for the static class
564 AddDataInt(response
, offset
, be_htobl(index
+ 9 - 1));
566 // Then, write the list of known class
567 for (it
= appList
.begin(); it
!= appList
.end(); it
++) {
568 JDWAppInfo
*appInfo
= &(it
->second
);
569 JDGClassList
*list
= &(appInfo
->classList
);
571 vector
<JDGClassEntry
>::iterator b
;
573 for (b
= list
->begin(); b
!= list
->end(); b
++) {
575 // I don't from class field, we have to filter the class view by JDB
576 if (b
->type
!= 0x824)
579 string str
= b
->getFullClassName();
581 str
= "L" + str
+ ";";
582 // replace_if(str.begin(), str.end(), bind2nd(equal_to<char>(),'.'), '/');
583 cout
<< hex
<< b
->index
<< "-" << str
<< "-" << endl
;
584 AddDataByte(response
, offset
, 0x01);
585 AddDataInt(response
, offset
, b
->index
);
586 AddDataString(response
, offset
, str
);
587 AddDataInt(response
, offset
, be_htobl(0x04));
591 // Then, write the default class (like RIM)
592 AddDataByte(response
, offset
, 0x01);
593 AddDataInt(response
, offset
, index
++);
594 AddDataString(response
, offset
, "Lcom/rim/resources/net_rim_rimsecuridlibRIMResources;");
595 AddDataInt(response
, offset
, be_htobl(0x04));
597 AddDataByte(response
, offset
, 0x01);
598 AddDataInt(response
, offset
, index
++);
599 AddDataString(response
, offset
, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimDatabaseFullException;");
600 AddDataInt(response
, offset
, be_htobl(0x04));
602 AddDataByte(response
, offset
, 0x01);
603 AddDataInt(response
, offset
, index
++);
604 AddDataString(response
, offset
, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimDecryptFailException;");
605 AddDataInt(response
, offset
, be_htobl(0x04));
607 AddDataByte(response
, offset
, 0x01);
608 AddDataInt(response
, offset
, index
++);
609 AddDataString(response
, offset
, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimDuplicateNameException;");
610 AddDataInt(response
, offset
, be_htobl(0x04));
612 AddDataByte(response
, offset
, 0x01);
613 AddDataInt(response
, offset
, index
++);
614 AddDataString(response
, offset
, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimDuplicateTokenException;");
615 AddDataInt(response
, offset
, be_htobl(0x04));
617 AddDataByte(response
, offset
, 0x01);
618 AddDataInt(response
, offset
, index
++);
619 AddDataString(response
, offset
, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimInvalidParamException;");
620 AddDataInt(response
, offset
, be_htobl(0x04));
622 AddDataByte(response
, offset
, 0x01);
623 AddDataInt(response
, offset
, index
++);
624 AddDataString(response
, offset
, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimSecurIDLib;");
625 AddDataInt(response
, offset
, be_htobl(0x04));
627 AddDataByte(response
, offset
, 0x01);
628 AddDataInt(response
, offset
, index
++);
629 AddDataString(response
, offset
, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimWrongDeviceIDException;");
630 AddDataInt(response
, offset
, be_htobl(0x04));
632 AddDataByte(response
, offset
, 0x01);
633 AddDataInt(response
, offset
, index
++);
634 AddDataString(response
, offset
, "Lnet/rim/device/cldc/impl/softtoken/rimsecuridlib/RimWrongFormFactorException;");
635 AddDataInt(response
, offset
, be_htobl(0x04));
638 response
.ReleaseBuffer(offset
);
641 size_t total_size
= response
.GetSize();
643 // Fill in the header values
644 MAKE_JDWPPACKETPTR_BUF(cpack
, response
.GetBuffer(total_size
));
645 Protocol::Packet
&packet
= *cpack
;
648 MAKE_JDWPPACKET(rpack
, cmd
);
650 packet
.length
= be_htobl(total_size
);
651 packet
.id
= rpack
->id
;
653 packet
.u
.response
.errorcode
= be_htobs(0);
655 response
.ReleaseBuffer(total_size
);
660 void JDWServer::CommandAllThreads(Data
&cmd
) {
663 // Get threads list from device
665 jvmdebug
->GetThreadsList(list
);
671 size_t offset
= JDWP_PACKET_HEADER_SIZE
+ JDWP_RESPONSE_HEADER_SIZE
;
673 // Indicate the number of element
674 AddDataInt(response
, offset
, be_htobl(list
.size()));
676 // Send all threads ID
677 vector
<JVMThreadsEntry
>::iterator b
= list
.begin();
678 for( ; b
!= list
.end(); b
++ ) {
679 JVMThreadsEntry entry
= *b
;
681 AddDataInt(response
, offset
, be_htobl(entry
.Id
));
684 response
.ReleaseBuffer(offset
);
687 size_t total_size
= response
.GetSize();
689 // Fill in the header values
690 MAKE_JDWPPACKETPTR_BUF(cpack
, response
.GetBuffer(total_size
));
691 Protocol::Packet
&packet
= *cpack
;
694 MAKE_JDWPPACKET(rpack
, cmd
);
696 packet
.length
= be_htobl(total_size
);
697 packet
.id
= rpack
->id
;
699 packet
.u
.response
.errorcode
= be_htobs(0);
701 response
.ReleaseBuffer(total_size
);
706 void JDWServer::CommandIdSizes(Data
&cmd
) {
709 MAKE_JDWPPACKET(rpack
, cmd
);
713 Protocol::Packet packet
;
715 size
= JDWP_PACKET_HEADER_SIZE
+ JDWP_RESPONSE_HEADER_SIZE
716 + JDWP_PACKETVIRTUALMACHINEIDSIZES_DATA_SIZE
;
718 packet
.length
= be_htobl(size
);
719 packet
.id
= rpack
->id
;
721 packet
.u
.response
.errorcode
= be_htobs(0);
722 packet
.u
.response
.u
.virtualMachine
.u
.IDSizes
.fieldIDSize
= be_htobl(0x04);
723 packet
.u
.response
.u
.virtualMachine
.u
.IDSizes
.methodIDSize
= be_htobl(0x04);
724 packet
.u
.response
.u
.virtualMachine
.u
.IDSizes
.objectIDSize
= be_htobl(0x04);
725 packet
.u
.response
.u
.virtualMachine
.u
.IDSizes
.referenceTypeIDSize
= be_htobl(0x04);
726 packet
.u
.response
.u
.virtualMachine
.u
.IDSizes
.frameIDSize
= be_htobl(0x04);
728 Data
response(&packet
, size
);
734 void JDWServer::CommandSuspend(Data
&cmd
) {
742 MAKE_JDWPPACKET(rpack
, cmd
);
746 Protocol::Packet packet
;
748 size
= JDWP_PACKET_HEADER_SIZE
+ JDWP_RESPONSE_HEADER_SIZE
;
750 packet
.length
= be_htobl(size
);
751 packet
.id
= rpack
->id
;
753 packet
.u
.response
.errorcode
= be_htobs(0);
755 Data
response(&packet
, size
);
761 void JDWServer::CommandResume(Data
&cmd
) {
766 jvmdebug
->Unknown06();
767 jvmdebug
->Unknown07();
768 jvmdebug
->Unknown08();
769 jvmdebug
->Unknown09();
770 jvmdebug
->Unknown10();
774 MAKE_JDWPPACKET(rpack
, cmd
);
778 Protocol::Packet packet
;
780 size
= JDWP_PACKET_HEADER_SIZE
+ JDWP_RESPONSE_HEADER_SIZE
;
782 packet
.length
= be_htobl(size
);
783 packet
.id
= rpack
->id
;
785 packet
.u
.response
.errorcode
= be_htobs(0);
787 Data
response(&packet
, size
);
793 void JDWServer::CommandClassPaths(Data
&cmd
) {
799 size_t offset
= JDWP_PACKET_HEADER_SIZE
+ JDWP_RESPONSE_HEADER_SIZE
;
801 AddDataString(response
, offset
, string(""));
802 AddDataInt(response
, offset
, be_htobl(0));
803 AddDataInt(response
, offset
, be_htobl(0));
805 response
.ReleaseBuffer(offset
);
808 size_t total_size
= response
.GetSize();
810 // Fill in the header values
811 MAKE_JDWPPACKETPTR_BUF(cpack
, response
.GetBuffer(total_size
));
812 Protocol::Packet
&packet
= *cpack
;
815 MAKE_JDWPPACKET(rpack
, cmd
);
817 packet
.length
= be_htobl(total_size
);
818 packet
.id
= rpack
->id
;
820 packet
.u
.response
.errorcode
= be_htobs(0);
822 response
.ReleaseBuffer(total_size
);
828 void JDWServer::CommandSet(Data
&cmd
) {
829 static int value
= 2;
833 MAKE_JDWPPACKET(rpack
, cmd
);
837 Protocol::Packet packet
;
839 size
= JDWP_PACKET_HEADER_SIZE
+ JDWP_RESPONSE_HEADER_SIZE
+ sizeof(uint32_t);
841 packet
.length
= be_htobl(size
);
842 packet
.id
= rpack
->id
;
844 packet
.u
.response
.errorcode
= be_htobs(0);
845 packet
.u
.response
.u
.value
= be_htobl(value
);
847 Data
response(&packet
, size
);