浏览代码

label-fixup

Tobias Waldekranz.com 8 年之前
父节点
当前提交
560267ddee
共有 1 个文件被更改,包括 60 次插入3 次删除
  1. 60 3
      ir.c

+ 60 - 3
ir.c

1
 #include <assert.h>
1
 #include <assert.h>
2
+#include <errno.h>
2
 #include <inttypes.h>
3
 #include <inttypes.h>
3
 #include <stdio.h>
4
 #include <stdio.h>
4
 #include <string.h>
5
 #include <string.h>
507
 	return ir;
508
 	return ir;
508
 }
509
 }
509
 
510
 
511
+
512
+/* ir->bpf generation */
513
+
510
 static void ir_bpf_vreg_replace(struct ir *ir, struct vinsn *last, int reg)
514
 static void ir_bpf_vreg_replace(struct ir *ir, struct vinsn *last, int reg)
511
 {
515
 {
512
 	struct vinsn *vi;
516
 	struct vinsn *vi;
525
 }
529
 }
526
 
530
 
527
 
531
 
528
-int ir_bpf_registerize_one(struct ir *ir, struct vinsn *last)
532
+static int ir_bpf_registerize_one(struct ir *ir, struct vinsn *last)
529
 {
533
 {
530
 	struct vinsn *vi;
534
 	struct vinsn *vi;
531
 	uint16_t clean = 0x3ff;
535
 	uint16_t clean = 0x3ff;
538
 			clean &= ~(1 << vi->insn.src);
542
 			clean &= ~(1 << vi->insn.src);
539
 		if (!(vi->insn.dst & vreg_base))
543
 		if (!(vi->insn.dst & vreg_base))
540
 			clean &= ~(1 << vi->insn.dst);
544
 			clean &= ~(1 << vi->insn.dst);
541
-		if (vi->insn.bpf.code == (BPF_JMP | BPF_CALL))
545
+		if ((BPF_CLASS(vi->insn.bpf.code) == BPF_JMP)
546
+		    && (BPF_OP(vi->insn.bpf.code) == BPF_CALL))
542
 			clean &= ~BPF_REG_CALLER_SAVE;
547
 			clean &= ~BPF_REG_CALLER_SAVE;
543
 	}
548
 	}
544
 
549
 
555
 	return -1;
560
 	return -1;
556
 }
561
 }
557
 
562
 
558
-int ir_bpf_registerize(struct ir *ir)
563
+static int ir_bpf_registerize(struct ir *ir)
559
 {
564
 {
560
 	struct vinsn *vi;
565
 	struct vinsn *vi;
561
 	int err = 0;
566
 	int err = 0;
576
 	return err;
581
 	return err;
577
 }
582
 }
578
 
583
 
584
+static int ir_bpf_jmp_resolve_one(struct ir *ir, struct vinsn *jmp)
585
+{
586
+	struct vinsn *vi;
587
+	int off = 0;
588
+
589
+	for (vi = jmp + 1; vi < &ir->vi[ir->len - 1]; vi++) {
590
+		switch (vi->vitype) {
591
+		case VI_INSN:
592
+			off++;
593
+			break;
594
+		case VI_LABEL:
595
+			if (vi->label != jmp->insn.bpf.off)
596
+				break;
597
+
598
+			jmp->insn.bpf.off = off;
599
+			return 0;
600
+		default:
601
+			break;
602
+		}
603
+	}
604
+
605
+	return -ENOENT;
606
+}
607
+
608
+static int ir_bpf_jmp_resolve(struct ir *ir)
609
+{
610
+	struct vinsn *vi;
611
+	int err;
612
+
613
+	for (vi = ir->vi; vi < &ir->vi[ir->len - 1]; vi++) {
614
+		if (vi->vitype != VI_INSN)
615
+			continue;
616
+
617
+		if ((BPF_CLASS(vi->insn.bpf.code) == BPF_JMP)
618
+		    && (vi->insn.bpf.off < 0)) {
619
+			err = ir_bpf_jmp_resolve_one(ir, vi);
620
+			if (err)
621
+				return err;
622
+		}
623
+	}
624
+
625
+	return 0;
626
+}
627
+
579
 int ir_bpf_generate(struct ir *ir)
628
 int ir_bpf_generate(struct ir *ir)
580
 {
629
 {
581
 	int err;
630
 	int err;
584
 	if (err)
633
 	if (err)
585
 		return err;
634
 		return err;
586
 
635
 
636
+	/* no instructions will be added/removed to the program after
637
+	 * this point, thus it is now safe to convert labeled jumps to
638
+	 * fixed offsets. */
639
+	
640
+	err = ir_bpf_jmp_resolve(ir);
641
+	if (err)
642
+		return err;
643
+
587
 	return 0;
644
 	return 0;
588
 }
645
 }