|
@@ -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, §ion_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, §ion_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, §ion_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, §ion_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;
|