Browse Source

Fix ELF parsing

Yann Weber 1 year ago
parent
commit
ead189dde2
2 changed files with 199 additions and 48 deletions
  1. 198
    48
      src/compile.c
  2. 1
    0
      tests/tests_compile.c

+ 198
- 48
src/compile.c View File

@@ -495,23 +495,153 @@ static void _child_cleanup(asmsh_asmc_child_t *child)
495 495
 }
496 496
 
497 497
 
498
+static int text_section_informations(const int fd,
499
+		const unsigned long int strtab_section_offset,
500
+		const unsigned long int section_header_off,
501
+		const unsigned short section_header_count,
502
+		const unsigned short section_header_sz,
503
+		unsigned long int *text_off, unsigned long int *text_sz)
504
+{
505
+	const int off_section_off = 0x18;
506
+
507
+	off_t off;
508
+	ssize_t rret;
509
+	int err;
510
+	unsigned long int strtab_offset, strtab_sz;
511
+
512
+	if((off = lseek(fd, strtab_section_offset + off_section_off, SEEK_SET)) != \
513
+			strtab_section_offset + off_section_off)
514
+	{
515
+		err=errno;
516
+		asmsh_log_perror("Unable to seek at strtab offset");
517
+		errno = err;
518
+		return -1;
519
+	}
520
+	if((rret = read(fd, &strtab_offset, 8)) != 8)
521
+	{
522
+		err=errno;
523
+		asmsh_log_perror("Unable to read strtab offset");
524
+		errno = err;
525
+		return -1;
526
+	}
527
+	if((rret = read(fd, &strtab_sz, 8)) != 8)
528
+	{
529
+		err=errno;
530
+		asmsh_log_perror("Unable to read strtab size");
531
+		errno = err;
532
+		return -1;
533
+	}
534
+
535
+	char strtab[strtab_sz];
536
+	if((off = lseek(fd, strtab_offset, SEEK_SET)) != strtab_offset)
537
+	{
538
+		err=errno;
539
+		asmsh_log_perror("Unable to seek at strtab");
540
+		errno = err;
541
+		return -1;
542
+	}
543
+	if((rret = read(fd, strtab, strtab_sz)) != strtab_sz)
544
+	{
545
+		err=errno;
546
+		asmsh_log_perror("Unable to read strtab");
547
+		errno = err;
548
+		return -1;
549
+	}
550
+
551
+
552
+	for(unsigned short i=0; i<section_header_count; i++)
553
+	{
554
+		unsigned long int cur_off = section_header_off + i*section_header_sz;
555
+		if((off = lseek(fd, cur_off, SEEK_SET)) != cur_off)
556
+		{
557
+			err=errno;
558
+			asmsh_log_perror("Unable to seek section");
559
+			errno = err;
560
+			return -1;
561
+		}
562
+		unsigned int name_off;
563
+		if((rret = read(fd, &name_off, 4)) != 4)
564
+		{
565
+			err=errno;
566
+			asmsh_log_perror("Unable to read section's name offset");
567
+			errno = err;
568
+			return -1;
569
+		}
570
+		if(name_off > strtab_sz)
571
+		{
572
+			asmsh_log_error("Invalid section's name offset");
573
+			errno=EINVAL;
574
+			return -1;
575
+		}
576
+		if(name_off == 0)
577
+		{
578
+			continue;
579
+		}
580
+		char *name = strtab + name_off;
581
+		if(strcmp(name, ".text") != 0)
582
+		{
583
+			continue;
584
+		}
585
+		unsigned int type;
586
+		if((rret = read(fd, &type, 4)) != 4)
587
+		{
588
+			err=errno;
589
+			asmsh_log_perror("Unable to read section type");
590
+			errno = err;
591
+			return -1;
592
+		}
593
+		if(type != 1)
594
+		{
595
+			asmsh_log_error("Section .text is not of type SHT_PROGBITS");
596
+			errno=EINVAL;
597
+			return -1;
598
+		}
599
+
600
+		if((off = lseek(fd, cur_off + off_section_off, SEEK_SET)) != \
601
+				cur_off + off_section_off)
602
+		{
603
+			err=errno;
604
+			asmsh_log_perror("Unable to seek at .text section offset");
605
+			errno = err;
606
+			return -1;
607
+		}
608
+
609
+		if((rret = read(fd, text_off, 8)) != 8)
610
+		{
611
+			err=errno;
612
+			asmsh_log_perror("Unable to read .text section offset");
613
+			errno = err;
614
+			return -1;
615
+		}
616
+		if((rret = read(fd, text_sz, 8)) != 8)
617
+		{
618
+			err=errno;
619
+			asmsh_log_perror("Unable to read .text section size");
620
+			errno = err;
621
+			return -1;
622
+		}
623
+		return 0;
624
+	}
625
+
626
+	asmsh_log_error("Cannot find .text section");
627
+	return -1;
628
+}
629
+
498 630
 int asmh_asmc_bytecode_from_obj(const char *objfile, asmsh_bytecode_t *bytecode)
499 631
 {
500
-	/*TODO parse ELF header instead of harcoded addr ?
501
-	  	at least check if the object file has the expected
502
-	  	size for the whole file.
503
-	   Header parsing is better in case the ELF organisation is
504
-	   platform/version dependent ?
505
-	*/
632
+	/*TODO check if the object file has the expected version etc ? */
633
+
506 634
 	// ELF 64 constants
507
-	const int bytecode_sz_off = 0x138;
508
-	const int bytecode_sz_sz = 4;
509
-	const int bytecode_off = 0x40;
635
+	const int off_section_header_off = 0x28;
636
+	const int off_section_header_sz = 0x3A;
637
+	const int off_section_header_count = 0x3C;
638
+	const int off_section_header_str = 0x3E;
510 639
 
511 640
 	int fd, err;
512 641
 	off_t off;
513 642
 	ssize_t rret;
514
-	unsigned int bytecode_sz;
643
+	unsigned long int section_header_off;
644
+	unsigned short section_header_sz, section_header_count, section_header_str;
515 645
 
516 646
 	if((fd = open(objfile, O_RDONLY)) < 0)
517 647
 	{
@@ -519,70 +649,90 @@ int asmh_asmc_bytecode_from_obj(const char *objfile, asmsh_bytecode_t *bytecode)
519 649
 		return -1;
520 650
 	}
521 651
 
522
-	if((off = lseek(fd, bytecode_sz_off, SEEK_SET)) != bytecode_sz_off)
652
+	if((off = lseek(fd, off_section_header_off, SEEK_SET)) != off_section_header_off)
523 653
 	{
524
-		/// TODO check off
525
-		perror("Unable to seek at bytecode size offset");
526 654
 		err = errno;
655
+		asmsh_log_perror("Unable to seek at section header offset");
527 656
 		goto err;
528 657
 	}
529
-
530
-	if((rret = read(fd, &bytecode_sz, bytecode_sz_sz)) != bytecode_sz_sz)
658
+	if((rret = read(fd, &section_header_off, 8)) != 8)
531 659
 	{
532 660
 		err = errno;
533
-		if(rret < 0)
534
-		{
535
-			perror("Unable to read bytecode size");
536
-		}
537
-		else
538
-		{
539
-			dprintf(2, "Unable to read the 4 bytes of the bytecode size %ld read instead\n", rret);
540
-			err = ENODATA;
541
-		}
661
+		asmsh_log_perror("Unable to read section header offset");
542 662
 		goto err;
543 663
 	}
544 664
 
545
-	if(bytecode_sz == 0)
665
+	if((off = lseek(fd, off_section_header_sz, SEEK_SET)) != off_section_header_sz)
666
+	{
667
+		err = errno;
668
+		asmsh_log_perror("Unable to seek at section header size");
669
+		goto err;
670
+	}
671
+	if((rret = read(fd, &section_header_sz, 2)) != 2)
546 672
 	{
547
-		asmsh_log_error("Null bytecode size");
548
-		err = ENODATA;
673
+		err = errno;
674
+		asmsh_log_perror("Unable to read section header size");
549 675
 		goto err;
550 676
 	}
551
-	if(bytecode_sz > sizeof(bytecode->bytes))
677
+
678
+	if((off = lseek(fd, off_section_header_count, SEEK_SET)) != off_section_header_count)
552 679
 	{
553
-		dprintf(2, "Bytecode size invalid, too many bytes (%d)\n",
554
-				bytecode_sz);
555
-		err = ENOBUFS;
680
+		err=errno;
681
+		asmsh_log_perror("Unable to seek at section header count");
556 682
 		goto err;
557 683
 	}
558
-	if((off = lseek(fd, bytecode_off, SEEK_SET)) != bytecode_off)
684
+	if((rret = read(fd, &section_header_count, 2)) != 2)
559 685
 	{
560
-		/// TODO check off
561
-		perror("Unable to seek at bytecode offset");
562 686
 		err = errno;
687
+		asmsh_log_perror("Unable to read section header count");
563 688
 		goto err;
564 689
 	}
565 690
 
566
-	bytecode->size = bytecode_sz;
567
-	if((rret = read(fd, bytecode->bytes, bytecode_sz)) != bytecode_sz)
691
+	if((off = lseek(fd, off_section_header_str, SEEK_SET)) != off_section_header_str)
568 692
 	{
569
-		err = errno;
570
-		if(rret < 0)
571
-		{
572
-			perror("Unable to read bytecode");
573
-		}
574
-		else
575
-		{
576
-			dprintf(2, "Unable to read the %d bytes of bytecode\n",
577
-					bytecode_sz);
578
-			err = ENODATA;
579
-		}
693
+		err=errno;
694
+		asmsh_log_perror("Unable to seek at section header str");
695
+		goto err;
696
+	}
697
+	if((rret = read(fd, &section_header_str, 2)) != 2)
698
+	{
699
+		err=errno;
700
+		asmsh_log_perror("Unable to read section header str");
580 701
 		goto err;
581 702
 	}
582 703
 
704
+	const unsigned long int strtab_section_offset = section_header_off + \
705
+							section_header_str * section_header_sz;
706
+	unsigned long int text_off, text_sz;
707
+	if(text_section_informations(fd, strtab_section_offset, \
708
+				section_header_off, section_header_count, \
709
+				section_header_sz, &text_off, &text_sz) < 0)
710
+	{
711
+		err=errno;
712
+		goto err;
713
+	}
714
+
715
+	if(text_sz > sizeof(bytecode->bytes))
716
+	{
717
+		asmsh_log_error("Too many bytes (%d) for an instruction", text_sz);
718
+		err=EINVAL;
719
+		goto err;
720
+	}
721
+	if((off = lseek(fd, text_off, SEEK_SET)) != text_off)
722
+	{
723
+		err=errno;
724
+		asmsh_log_perror("Unable to seek at text section");
725
+		goto err;
726
+	}
727
+	if((rret = read(fd, &bytecode->bytes, text_sz)) != text_sz)
728
+	{
729
+		err=errno;
730
+		asmsh_log_perror("Unable to read text section");
731
+		goto err;
732
+	}
733
+	bytecode->size = text_sz;
583 734
 	close(fd);
584 735
 	return 0;
585
-
586 736
 err:
587 737
 	close(fd);
588 738
 	errno = err;

+ 1
- 0
tests/tests_compile.c View File

@@ -157,6 +157,7 @@ static const compile_sample_t comp_samples[] = {
157 157
 	{{"\x31\xc0\0", 2}, "xor %rax, %rax"},
158 158
 	{{"\x53\0", 1}, "push %rbx"},
159 159
 	{{"\x0f\x05\0", 2}, "syscall"},
160
+	{{"\x48\xb8\x78\x56\x34\x12\x00\x00\x00\x00", 10}, "movabs $0x12345678, %rax"},
160 161
 };
161 162
 
162 163
 static const int comp_samples_sz = sizeof(comp_samples)/sizeof(*comp_samples);

Loading…
Cancel
Save