classloader.c
1 /* 2 * Bean Java VM 3 * Copyright (C) 2005-2025 Christian Lins <christian@lins.me> 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include <debug.h> 19 #include <platform.h> 20 #include <vm.h> 21 22 extern VM* vm; 23 24 Class* Class_new() 25 { 26 /* Create class struct */ 27 vm->classloader->loaded_classes_num++; 28 vm->classloader->loaded_classes = (Class*)realloc( 29 vm->classloader->loaded_classes, 30 sizeof(Class) * vm->classloader->loaded_classes_num); 31 32 Class* class = &vm->classloader->loaded_classes[vm->classloader->loaded_classes_num - 1]; 33 34 return class; 35 } 36 37 /** 38 * Looks for cinit method and - if available - runs it on current thread. 39 */ 40 void Class_init(Class* obj) { 41 42 } 43 44 Classloader* Classloader_new() { 45 Classloader* classloader = (Classloader*)malloc(sizeof(Classloader)); 46 47 classloader->loaded_classes = NULL; 48 classloader->loaded_classes_num = 0; 49 50 return classloader; 51 } 52 53 void Classloader_destroy(Classloader* ptr) { 54 free(ptr); 55 } 56 57 static 58 void _freadb(unsigned char* buf, int count, FILE* file) { 59 if (fread(buf, 1, count, file) != count) { 60 printf("WARNING: fread returned unexpected byte count\n"); 61 } 62 } 63 64 static 65 void _read_constant_fieldref(int n, FILE* classfile, Class* class) { 66 unsigned char buffer2[2] = { 0, 0 }; 67 68 // Allocating memory for REF_INFO 69 class->ConstantPool[n - 1].Data = malloc(sizeof(struct CONSTANT_REF_INFO)); 70 71 // Read class index 72 _freadb(buffer2, 2, classfile); 73 ((struct CONSTANT_REF_INFO*)class->ConstantPool[n - 1].Data)->ClassIndex 74 = BufferToShort(buffer2); 75 76 // Read name and type index 77 _freadb(buffer2, 2, classfile); 78 ((struct CONSTANT_REF_INFO*)class->ConstantPool[n - 1].Data)->NameAndTypeIndex 79 = BufferToShort(buffer2); 80 81 dmsg("CONSTANTPOOL_FIELDREF"); 82 } 83 84 static 85 void _read_constant_methodref(int n, FILE* classfile, Class* class) { 86 unsigned char buffer2[2] = { 0, 0 }; 87 88 // Allocating memory for REF_INFO 89 class->ConstantPool[n - 1].Data = malloc(sizeof(struct CONSTANT_REF_INFO)); 90 91 // Read class index 92 _freadb(buffer2, 2, classfile); 93 ((struct CONSTANT_REF_INFO*)class->ConstantPool[n - 1].Data)->ClassIndex = 94 BufferToShort(buffer2); 95 96 // Read name and type index 97 _freadb(buffer2, 2, classfile); 98 ((struct CONSTANT_REF_INFO *) class->ConstantPool[n - 1]. 99 Data)->NameAndTypeIndex = BufferToShort(buffer2); 100 101 dmsg("CONSTANTPOOL_METHODREF"); 102 } 103 104 static 105 void _read_constant_interfacemethodref(int n, FILE* classfile, Class* class) { 106 unsigned char buffer2[2] = { 0, 0 }; 107 108 // Allocating memory for REF_INFO 109 class->ConstantPool[n - 1].Data = malloc(sizeof(struct CONSTANT_REF_INFO)); 110 111 // Read class index 112 _freadb(buffer2, 2, classfile); 113 ((struct CONSTANT_REF_INFO*)class->ConstantPool[n - 1].Data)->ClassIndex = 114 BufferToShort(buffer2); 115 116 // Read name and type index 117 _freadb(buffer2, 2, classfile); 118 ((struct CONSTANT_REF_INFO *) class->ConstantPool[n - 1]. 119 Data)->NameAndTypeIndex = BufferToShort(buffer2); 120 121 dmsg("CONSTANTPOOL_INTERFACEMETHODREF"); 122 } 123 124 static 125 void _read_constant_string(int n, FILE* classfile, Class* class) { 126 unsigned char buffer2[2] = { 0, 0 }; 127 128 // Allocating memory for STRING_INFO 129 class->ConstantPool[n - 1].Data = malloc(sizeof(struct CONSTANT_STRING_INFO)); 130 131 // Read string index 132 _freadb(buffer2, 2, classfile); 133 ((struct CONSTANT_STRING_INFO *) class->ConstantPool[n - 1].Data)->StringIndex = 134 BufferToShort(buffer2); 135 136 dmsg("CONSTANTPOOL_STRING"); 137 } 138 139 static 140 void _read_constant_utf8(int n, FILE* classfile, Class* class, int* attributeCodeIndex) { 141 unsigned char buffer2[2] = { 0, 0 }; 142 n = n - 1; // ConstantPool starts at index 0 143 144 // Allocating memory for UTF8_INFO 145 class->ConstantPool[n].Data = malloc(sizeof(struct CONSTANT_UTF8_INFO)); 146 147 // Read string length 148 _freadb(buffer2, 2, classfile); 149 uint16_t len = BufferToShort(buffer2); 150 ((struct CONSTANT_UTF8_INFO*)class->ConstantPool[n].Data)->Length = len; 151 152 // Allocating memory for string 153 ((struct CONSTANT_UTF8_INFO*)class->ConstantPool[n].Data)->Text 154 = (char*)malloc(len * sizeof(char) + 1); 155 156 // Read string 157 _freadb( 158 (unsigned char*)((struct CONSTANT_UTF8_INFO*)class->ConstantPool[n].Data)->Text, 159 len, classfile); 160 161 // Terminating zero character 162 ((struct CONSTANT_UTF8_INFO*)class->ConstantPool[n].Data)->Text[ 163 ((struct CONSTANT_UTF8_INFO*)class->ConstantPool[n].Data)->Length] = 0; 164 165 #ifdef DEBUG 166 printf("CONSTANTPOOL_UTF8 -> %s (len=%d)\n", 167 ((struct CONSTANT_UTF8_INFO *)class->ConstantPool[n].Data)->Text, 168 ((struct CONSTANT_UTF8_INFO *)class->ConstantPool[n].Data)->Length); 169 #endif 170 171 // Check for default attribute names 172 if (strcmp(((struct CONSTANT_UTF8_INFO*)class->ConstantPool[n].Data)->Text, "Code") == 0) { 173 *attributeCodeIndex = n + 1; // From zero-based index to class file index 174 } 175 } 176 177 static 178 void _read_constant_integer(int n, FILE* classfile, Class* class) { 179 unsigned char buffer4[4] = { 0, 0, 0, 0 }; 180 class->ConstantPool[n - 1].Data = malloc(sizeof(struct CONSTANT_INTEGER_INFO)); 181 182 // Read integer of four bytes 183 _freadb(buffer4, 4, classfile); 184 ((struct CONSTANT_INTEGER_INFO *)class->ConstantPool[n - 1].Data)->Value = 185 BufferToInt(buffer4); 186 187 dmsg("CONSTANTPOOL_INTEGER"); 188 } 189 190 static 191 void _read_constant_long(int n, FILE* classfile, Class* class) { 192 uint64_t buffer8 = 0; 193 194 class->ConstantPool[n - 1].Data = malloc(sizeof(struct CONSTANT_LONG_INFO)); 195 _freadb((void*)&buffer8, 8, classfile); 196 buffer8 = bswp64(buffer8); 197 ((struct CONSTANT_LONG_INFO *)class->ConstantPool[n - 1].Data)->Value = buffer8; 198 dmsg("CONSTANTPOOL_LONG"); 199 } 200 201 static 202 void _read_constant_float(int n, FILE* classfile, Class* class) { 203 unsigned char buffer4[4] = { 0, 0, 0, 0 }; 204 class->ConstantPool[n - 1].Data = malloc(sizeof(struct CONSTANT_FLOAT_INFO)); 205 206 // Read float 207 _freadb(buffer4, 4, classfile); 208 ((struct CONSTANT_FLOAT_INFO *)class->ConstantPool[n - 1].Data)->Value = 209 (float)BufferToInt(buffer4); 210 211 dmsg("CONSTANTPOOL_FLOAT"); 212 } 213 214 static 215 void _read_constant_double(int n, FILE* classfile, Class* class) { 216 double buf = 0; 217 218 class->ConstantPool[n - 1].Data = malloc(sizeof(struct CONSTANT_DOUBLE_INFO)); 219 220 // TODO: Check if this really works 221 _freadb((void*)&buf, 8, classfile); 222 ((struct CONSTANT_DOUBLE_INFO*)class->ConstantPool[n-1].Data)->Value = buf; 223 224 dmsg("CONSTANTPOOL_DOUBLE"); 225 } 226 227 static 228 void _read_constant_nameandtype(int n, FILE* classfile, Class* class) { 229 unsigned char buffer2[2] = { 0, 0 }; 230 231 // Allocating memory for NAMEANDTYPE_INFO 232 class->ConstantPool[n - 1].Data = 233 malloc(sizeof(struct CONSTANT_NAMETYPE_INFO)); 234 235 // Read name index 236 _freadb(buffer2, 2, classfile); 237 ((struct CONSTANT_NAMETYPE_INFO *)class->ConstantPool[n - 1].Data)->NameIndex 238 = BufferToShort(buffer2); 239 240 // Read descriptor index 241 _freadb(buffer2, 2, classfile); 242 ((struct CONSTANT_NAMETYPE_INFO *)class->ConstantPool[n - 1].Data)->DescriptorIndex 243 = BufferToShort(buffer2); 244 245 dmsg("CONSTANTPOOL_NAMETYPE"); 246 } 247 248 static 249 void _read_constant_class(int n, FILE* classfile, Class* class) { 250 unsigned char buffer2[2] = { 0, 0 }; 251 252 // Allocating memory for CLASS_INFO 253 class->ConstantPool[n - 1].Data = malloc(sizeof(struct CONSTANT_CLASS_INFO)); 254 255 // Read name index 256 _freadb(buffer2, 2, classfile); 257 ((struct CONSTANT_CLASS_INFO *)class->ConstantPool[n - 1].Data)->NameIndex = 258 BufferToShort(buffer2); 259 260 #ifdef DEBUG 261 printf("CONSTANTPOOL_CLASS (NameIndex=%d) read.\n", ((struct CONSTANT_CLASS_INFO *) 262 class->ConstantPool[n - 1].Data)->NameIndex); 263 #endif 264 } 265 266 static 267 void _read_field(int n, FILE* classfile, Class* class) { 268 unsigned char buffer2[2] = { 0, 0 }; 269 unsigned char buffer4[4] = { 0, 0, 0, 0 }; 270 271 // Read access flags 272 _freadb(buffer2, 2, classfile); 273 class->fieldInfos[n].AccessFlags = BufferToShort(buffer2); 274 275 // Read name index 276 _freadb(buffer2, 2, classfile); 277 class->fieldInfos[n].NameIndex = BufferToShort(buffer2); 278 279 // Read descriptor index 280 _freadb(buffer2, 2, classfile); 281 class->fieldInfos[n].DescriptorIndex = BufferToShort(buffer2); 282 283 // Read attributes count 284 _freadb(buffer2, 2, classfile); 285 class->fieldInfos[n].AttributesNum = BufferToShort(buffer2); 286 287 // Read attributes 288 class->fieldInfos[n].Attributes = (struct ATTRIBUTE_INFO *) 289 malloc(sizeof(struct ATTRIBUTE_INFO) * class->fieldInfos[n].AttributesNum); 290 for (int m = 0; m < class->fieldInfos[n].AttributesNum; m++) { 291 // Read attribute name index 292 _freadb(buffer2, 2, classfile); 293 class->fieldInfos[n].Attributes[m].AttributeNameIndex = BufferToShort(buffer2); 294 295 // Read length of info array 296 _freadb(buffer4, 4, classfile); 297 class->fieldInfos[n].Attributes[m].AttributeLength = BufferToInt(buffer4); 298 299 // Allocate space for infos 300 class->fieldInfos[n].Attributes[m].Info = 301 (unsigned char*) malloc(class->fieldInfos[n].Attributes[m].AttributeLength); 302 _freadb(class->fieldInfos[n].Attributes[m].Info, 303 class->fieldInfos[n].Attributes[m].AttributeLength, 304 classfile); 305 } 306 } 307 308 void _read_attribute_info(struct ATTRIBUTE_INFO * attributeInfo, FILE* classfile) 309 { 310 unsigned char buffer2[2]; 311 unsigned char buffer4[4]; 312 313 // Read attribute name index 314 _freadb(buffer2, 2, classfile); 315 attributeInfo->AttributeNameIndex = BufferToShort(buffer2); 316 317 // Read length of info array 318 _freadb(buffer4, 4, classfile); 319 attributeInfo->AttributeLength = BufferToInt(buffer4); 320 321 // Allocate space for infos 322 attributeInfo->Info = (unsigned char*) malloc(sizeof(unsigned char) * 323 attributeInfo->AttributeLength); 324 325 if (attributeInfo->Info == NULL) { 326 printf("malloc failed\n"); 327 return; 328 } 329 330 _freadb(attributeInfo->Info, attributeInfo->AttributeLength, classfile); 331 } 332 333 static 334 void _read_method_info(Class * class, FILE* classfile, int mainIndex, 335 int attributeCodeIndex) 336 { 337 unsigned char buffer2[2]; 338 dbgmsg("Begin reading method_info_t...\n"); 339 340 // Read methods count 341 _freadb(buffer2, 2, classfile); 342 class->MethodsNum = BufferToShort(buffer2); 343 344 // Read methods 345 class->Methods = (Method*)malloc(sizeof(Method) * class->MethodsNum); 346 347 if (class->Methods == NULL) { 348 printf("malloc failed\n"); 349 return; 350 } 351 352 for (int n = 0; n < class->MethodsNum; n++) { 353 // Read access flags 354 _freadb(buffer2, 2, classfile); 355 class->Methods[n].AccessFlags = BufferToShort(buffer2); 356 357 // Read name index 358 _freadb(buffer2, 2, classfile); 359 class->Methods[n].NameIndex = BufferToShort(buffer2); 360 if (class->Methods[n].NameIndex == mainIndex) { 361 class->MainMethodIndex = n + 1; 362 } 363 364 // Read descriptor index 365 _freadb(buffer2, 2, classfile); 366 class->Methods[n].DescriptorIndex = BufferToShort(buffer2); 367 368 // Read attributes count 369 _freadb(buffer2, 2, classfile); 370 class->Methods[n].AttributesNum = BufferToShort(buffer2); 371 372 // Read attributes 373 class->Methods[n].Attributes = (struct ATTRIBUTE_INFO *) 374 malloc(sizeof(struct ATTRIBUTE_INFO) * class->Methods[n].AttributesNum); 375 376 for (int m = 0; m < class->Methods[n].AttributesNum; m++) { 377 // Read standard attribute 378 _read_attribute_info(class->Methods[n].Attributes + m, classfile); 379 380 // Check for special attributes 381 if (class->Methods[n].Attributes[m].AttributeNameIndex == attributeCodeIndex) { 382 dbgmsg("Code Info detected\n"); 383 384 class->Methods[n].CodeInfo = (struct ATTRIBUTE_INFO_CODE *) 385 malloc(sizeof(struct ATTRIBUTE_INFO_CODE)); 386 class->Methods[n].CodeInfo->AttributeNameIndex = attributeCodeIndex; 387 388 // Attribute length 389 class->Methods[n].CodeInfo->AttributeLength 390 = class->Methods[n].Attributes[m].AttributeLength; 391 392 // Read max. stack (2 Byte) */ 393 class->Methods[n].operandStackSize = 394 BufferToShort(class->Methods[n].Attributes[m].Info + 0); 395 396 /* Allocate operand stack */ 397 /*vmclass->Methods[n].StackFrameRef.OperandStack 398 = (struct OperandStackFrame*)malloc(sizeof(struct OperandStackFrame) * vmclass->Methods[n].StackFrameRef.OperandStackSize); 399 */ 400 // Read max locals (2 Byte) 401 class->Methods[n].localVarsLen = 402 BufferToShort(class->Methods[n].Attributes[m].Info + 2); 403 /* Where is StackFrameRef.localVars initialized? 404 * Does it make sense to store the localVarsLen in a stackframe? 405 * */ 406 407 // Read code length (4 Byte) 408 class->Methods[n].CodeInfo->CodeLength = 409 BufferToInt(class->Methods[n].Attributes[m].Info + 4); 410 #ifdef DEBUG 411 printf("Code Length %d\n", class->Methods[n].CodeInfo->CodeLength); 412 #endif 413 414 // Code 415 class->Methods[n].CodeInfo->Code = malloc(sizeof(unsigned char) * 416 class->Methods[n].CodeInfo->CodeLength); 417 for (int i = 0; i < (int)class->Methods[n].CodeInfo->CodeLength; i++) 418 class->Methods[n].CodeInfo->Code[i] = *(class->Methods[n].Attributes[m].Info + 8 + i); 419 420 // Exception table length (2 Byte) 421 class->Methods[n].CodeInfo->ExceptionTableLength = 422 BufferToShort(class->Methods[n].Attributes[m].Info + 8 + 423 class->Methods[n].CodeInfo->CodeLength); 424 #ifdef DEBUG 425 printf("Exception Table Length: %d\n", 426 class->Methods[n].CodeInfo->ExceptionTableLength); 427 #endif 428 429 // Exception Table 430 // TODO 431 432 // Attributes num 433 class->Methods[n].CodeInfo->AttributesNum = 434 BufferToShort(class->Methods[n].Attributes[m].Info + 435 10 + 436 class->Methods[n]. 437 CodeInfo->CodeLength + 438 class->Methods[n]. 439 CodeInfo->ExceptionTableLength * 8); 440 #ifdef DEBUG 441 printf("AttributesNum: %d\n", class->Methods[n].CodeInfo->AttributesNum); 442 #endif 443 444 // Attribute Infos 445 class->Methods[n].CodeInfo->Attributes = (struct ATTRIBUTE_INFO *) 446 malloc(sizeof(struct ATTRIBUTE_INFO) * 447 class->Methods[n].CodeInfo->AttributesNum); 448 } 449 } 450 } 451 452 // Set fully qualified name 453 class->QualifiedName = ""; // TODO 454 } 455 456 bool Classloader_loadClass(FILE* classfile, Class* class) { 457 if (classfile == nullptr) { 458 #ifdef DEBUG 459 printf("IO-Error: %u\n", ferror(classfile)); 460 #endif 461 return false; 462 } 463 464 int attributeCodeIndex = 0; 465 int mainIndex = 0; 466 unsigned char buffer1 = 0; 467 unsigned char buffer2[2] = { 0, 0 }; 468 unsigned char buffer4[4] = { 0, 0, 0, 0 }; 469 470 // Set init values 471 class->AccessFlags = 0x0000; 472 473 dbgmsg("Class file opened."); 474 475 // Read Magic 476 _freadb(buffer4, 4, classfile); 477 if (memcmp(buffer4, "\xCA\xFE\xBA\xBE", 4) != 0) { 478 printf("Class file has invalid magic! Read: %x %x %x %x\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]); 479 return false; 480 } 481 482 // Read minor version 483 _freadb(buffer2, 2, classfile); 484 class->Version.Minor = BufferToShort(buffer2); 485 486 // Read major version 487 _freadb(buffer2, 2, classfile); 488 class->Version.Major = BufferToShort(buffer2); 489 #ifdef DEBUG 490 printf("Class Version: %d.%d\n", class->Version.Major, class->Version.Minor); 491 #endif 492 493 // Read constant pool count 494 _freadb(buffer2, 2, classfile); 495 class->ConstantPoolNum = BufferToShort(buffer2); 496 #ifdef DEBUG 497 printf("Constant pool count: %d\n", class->ConstantPoolNum); 498 #endif 499 500 // Allocate memory for constant pool 501 class->ConstantPool = (struct CONSTANTPOOL*)malloc( 502 class->ConstantPoolNum * sizeof(struct CONSTANTPOOL)); 503 504 // Read constants from pool 505 for (int n = 1; n < class->ConstantPoolNum; n++) { 506 _freadb(&buffer1, 1, classfile); 507 class->ConstantPool[n - 1].Tag = buffer1; 508 509 #ifdef DEBUG 510 printf("%d: Constant Type %d\t", n, buffer1); 511 #endif 512 513 switch (class->ConstantPool[n - 1].Tag) { 514 case CONSTANTPOOL_FIELDREF: { 515 _read_constant_fieldref(n, classfile, class); 516 break; 517 } 518 case CONSTANTPOOL_CLASS: { 519 _read_constant_class(n, classfile, class); 520 break; 521 } 522 case CONSTANTPOOL_METHODREF: { 523 _read_constant_methodref(n, classfile, class); 524 break; 525 } 526 case CONSTANTPOOL_INTERFACEMETHODREF: { 527 _read_constant_interfacemethodref(n, classfile, class); 528 break; 529 } 530 case CONSTANTPOOL_STRING: { 531 _read_constant_string(n, classfile, class); 532 break; 533 } 534 case CONSTANTPOOL_INTEGER: { 535 _read_constant_integer(n, classfile, class); 536 break; 537 } 538 case CONSTANTPOOL_FLOAT: { 539 _read_constant_float(n, classfile, class); 540 break; 541 } 542 case CONSTANTPOOL_LONG: { 543 _read_constant_long(n, classfile, class); 544 break; 545 } 546 case CONSTANTPOOL_DOUBLE: { 547 _read_constant_double(n, classfile, class); 548 break; 549 } 550 case CONSTANTPOOL_NAMEANDTYPE: { 551 _read_constant_nameandtype(n, classfile, class); 552 break; 553 } 554 case CONSTANTPOOL_UTF8: { 555 _read_constant_utf8(n, classfile, class, &attributeCodeIndex); 556 break; 557 } 558 default: { 559 printf("Unknown constant type: %d!\n", class->ConstantPool[n - 1].Tag); 560 fclose(classfile); 561 return false; 562 } 563 } // end switch 564 } // end for 565 566 // Read access flags 567 _freadb(buffer2, 2, classfile); 568 class->AccessFlags = BufferToShort(buffer2); 569 570 // Read this class index 571 _freadb(buffer2, 2, classfile); 572 class->ThisClassIndex = BufferToShort(buffer2); 573 574 // Read super class index 575 _freadb(buffer2, 2, classfile); 576 class->SuperClassIndex = BufferToShort(buffer2); 577 578 // Read interface count 579 _freadb(buffer2, 2, classfile); 580 class->InterfacesNum = BufferToShort(buffer2); 581 582 // Read interface indices 583 class->Interfaces = 584 (unsigned short*)malloc(sizeof(unsigned short) * class->InterfacesNum); 585 for (int n = 0; n < class->InterfacesNum; n++) { 586 _freadb(buffer2, 2, classfile); 587 class->Interfaces[n] = BufferToShort(buffer2); 588 } 589 590 // Read fields count 591 _freadb(buffer2, 2, classfile); 592 class->fieldsNum = BufferToShort(buffer2); 593 594 // Read field infos 595 class->fieldInfos = (FieldInfo*)malloc(sizeof(FieldInfo) * class->fieldsNum); 596 class->fieldValues = (Varframe*)malloc(sizeof(Varframe) * class->fieldsNum); 597 598 for (int n = 0; n < class->fieldsNum; n++) { 599 _read_field(n, classfile, class); 600 } 601 602 // Read methods 603 _read_method_info(class, classfile, mainIndex, attributeCodeIndex); 604 605 // Read attributes count 606 _freadb(buffer2, 2, classfile); 607 class->AttributesNum = BufferToShort(buffer2); 608 609 // Read attributes 610 class->Attributes = (struct ATTRIBUTE_INFO *) 611 malloc(sizeof(struct ATTRIBUTE_INFO) * class->AttributesNum); 612 for (int m = 0; m < class->AttributesNum; m++) { 613 // Read attribute name index 614 _freadb(buffer2, 2, classfile); 615 class->Attributes[m].AttributeNameIndex = BufferToShort(buffer2); 616 617 // Read length of info array 618 _freadb(buffer4, 4, classfile); 619 class->Attributes[m].AttributeLength = BufferToInt(buffer4); 620 621 // Allocate space for infos 622 class->Attributes[m].Info = (unsigned char*)malloc(sizeof(struct ATTRIBUTE_INFO) * 623 class->Attributes[m].AttributeLength); 624 _freadb(class->Attributes[m].Info, class->Attributes[m].AttributeLength, classfile); 625 } 626 627 // Trigger EOF 628 fgetc(classfile); 629 630 if (!feof(classfile)) { 631 printf("Class not wellformed: unused data at end of file!\n"); 632 #ifdef DEBUG 633 while(!feof(classfile)) { 634 unsigned char buf = 0; 635 _freadb(&buf, 1, classfile); 636 printf("0x%X ", buf); 637 } 638 printf("\n"); 639 #endif 640 } 641 642 fclose(classfile); 643 644 return true; 645 } 646 647 FILE* find_class_file(const char* class) 648 { 649 #ifdef ATMEGA 650 // TODO FIXME 651 return NULL; 652 #endif 653 654 #ifdef DEBUG 655 printf("Using %s as classpath\n", vm->classpath); 656 #endif 657 658 // Argument class is the Java class name with slashes as separator 659 // instead of points, e.g. "java/lang/System". 660 char* class_file = malloc(sizeof(char) * (sizeof(class) + sizeof(".class"))); 661 strcpy(class_file, class); 662 663 // At first we add ".class", 7 is length of str plus '\0' 664 strncat(class_file, ".class", 7); 665 666 // Then we try all classpaths for the given class file 667 // (currently there is only one classpath (and ".")) 668 FILE* file = fopen(class_file, "rb"); 669 #ifdef DEBUG 670 printf("Trying '%s'\n", class_file); 671 #endif 672 if (file != NULL) { 673 free(class_file); 674 return file; 675 } 676 677 // FIXME 678 char* class_file_path = malloc(sizeof(char) * 679 (strlen(class_file) + strlen(vm->classpath) + 1)); 680 strcpy(class_file_path, vm->classpath); 681 class_file_path = strncat(class_file_path, class_file, strlen(class_file)); 682 file = fopen(class_file_path, "rb"); 683 #ifdef DEBUG 684 printf("Trying '%s'\n", class_file_path); 685 #endif 686 687 // If we found it, we return the FILE handle to it 688 free(class_file); 689 return file; 690 }