Пример #1
0
void
patch(void)
{
	vlong c, vexit;
	Prog *p, *q;
	Sym *s;
	int a;

	if(debug['v'])
		Bprint(&bso, "%5.2f patch\n", cputime());
	Bflush(&bso);
	mkfwd();
	s = lookup("exit", 0);
	vexit = s->value;
	for(p = firstp; p != P; p = p->link) {
		a = p->as;
		if(a == ATEXT)
			curtext = p;
		if((a == AJAL || a == AJMP || a == ARET) &&
		   p->to.type != D_BRANCH && p->to.sym != S) {
			s = p->to.sym;
			if(s->type != STEXT) {
				diag("undefined: %s\n%P", s->name, p);
				s->type = STEXT;
				s->value = vexit;
			}
			p->to.offset = s->value;
			p->to.type = D_BRANCH;
		}
		if(p->to.type != D_BRANCH)
			continue;
		c = p->to.offset;
		for(q = firstp; q != P;) {
			if(q->forwd != P)
			if(c >= q->forwd->pc) {
				q = q->forwd;
				continue;
			}
			if(c == q->pc)
				break;
			q = q->link;
		}
		if(q == P) {
			diag("branch out of range %lld\n%P", c, p);
			p->to.type = D_NONE;
		}
		p->cond = q;
	}

	for(p = firstp; p != P; p = p->link) {
		if(p->as == ATEXT)
			curtext = p;
		if(p->cond != P) {
			p->cond = brloop(p->cond);
			if(p->cond != P)
			if(p->to.type == D_BRANCH)
				p->to.offset = p->cond->pc;
		}
	}
}
Пример #2
0
Файл: pass.c Проект: pipul/lab
void
patch(void)
{
	int32 c;
	Prog *p, *q;
	Sym *s;
	int32 vexit;
	Sym *plan9_tos;

	if(debug['v'])
		Bprint(&bso, "%5.2f mkfwd\n", cputime());
	Bflush(&bso);
	mkfwd();
	if(debug['v'])
		Bprint(&bso, "%5.2f patch\n", cputime());
	Bflush(&bso);
	s = lookup("exit", 0);
	vexit = s->value;
	
	plan9_tos = S;
	if(HEADTYPE == Hplan9x32)
		plan9_tos = lookup("_tos", 0);
	
	for(cursym = textp; cursym != nil; cursym = cursym->next) {
		for(p = cursym->text; p != P; p = p->link) {
			if(HEADTYPE == Hwindows) {
				// Convert
				//   op	  n(GS), reg
				// to
				//   MOVL 0x14(FS), reg
				//   op	  n(reg), reg
				// The purpose of this patch is to fix some accesses
				// to extern register variables (TLS) on Windows, as
				// a different method is used to access them.
				if(p->from.type == D_INDIR+D_GS
				&& p->to.type >= D_AX && p->to.type <= D_DI) {
					q = appendp(p);
					q->from = p->from;
					q->from.type = D_INDIR + p->to.type;
					q->to = p->to;
					q->as = p->as;
					p->as = AMOVL;
					p->from.type = D_INDIR+D_FS;
					p->from.offset = 0x14;
				}
			}
			if(HEADTYPE == Hlinux) {
				// Running binaries under Xen requires using
				//	MOVL 0(GS), reg
				// and then off(reg) instead of saying off(GS) directly
				// when the offset is negative.
				if(p->from.type == D_INDIR+D_GS && p->from.offset < 0
				&& p->to.type >= D_AX && p->to.type <= D_DI) {
					q = appendp(p);
					q->from = p->from;
					q->from.type = D_INDIR + p->to.type;
					q->to = p->to;
					q->as = p->as;
					p->as = AMOVL;
					p->from.type = D_INDIR+D_GS;
					p->from.offset = 0;
				}
			}
			if(HEADTYPE == Hplan9x32) {
				if(p->from.type == D_INDIR+D_GS
				&& p->to.type >= D_AX && p->to.type <= D_DI) {
					q = appendp(p);
					q->from = p->from;
					q->from.type = D_INDIR + p->to.type;
					q->to = p->to;
					q->as = p->as;
					p->as = AMOVL;
					p->from.type = D_EXTERN;
					p->from.sym = plan9_tos;
					p->from.offset = 0;
				}
			}
			if((p->as == ACALL && p->to.type != D_BRANCH) || (p->as == AJMP && p->to.type != D_BRANCH)) {
				s = p->to.sym;
				if(p->to.type == D_INDIR+D_ADDR) {
					 /* skip check if this is an indirect call (CALL *symbol(SB)) */
					 continue;
				} else if(s) {
					if(debug['c'])
						Bprint(&bso, "%s calls %s\n", TNAME, s->name);
					if((s->type&~SSUB) != STEXT) {
						/* diag prints TNAME first */
						diag("undefined: %s", s->name);
						s->type = STEXT;
						s->value = vexit;
						continue;	// avoid more error messages
					}
					if(s->text == nil)
						continue;
					p->to.type = D_BRANCH;
					p->to.offset = s->text->pc;
					p->pcond = s->text;
					continue;
				}
			}
			if(p->to.type != D_BRANCH)
				continue;
			c = p->to.offset;
			for(q = cursym->text; q != P;) {
				if(c == q->pc)
					break;
				if(q->forwd != P && c >= q->forwd->pc)
					q = q->forwd;
				else
					q = q->link;
			}
			if(q == P) {
				diag("branch out of range in %s (%#ux)\n%P [%s]",
					TNAME, c, p, p->to.sym ? p->to.sym->name : "<nil>");
				p->to.type = D_NONE;
			}
			p->pcond = q;
		}
	}

	for(cursym = textp; cursym != nil; cursym = cursym->next) {
		if(cursym->text == nil || cursym->p != nil)
			continue;

		for(p = cursym->text; p != P; p = p->link) {
			p->mark = 0;	/* initialization for follow */
			if(p->pcond != P) {
				p->pcond = brloop(p->pcond);
				if(p->pcond != P)
				if(p->to.type == D_BRANCH)
					p->to.offset = p->pcond->pc;
			}
		}
	}
}
Пример #3
0
void
patch(void)
{
	int32 c, vexit;
	Prog *p, *q;
	Sym *s, *s1;
	int a;

	if(debug['v'])
		Bprint(&bso, "%5.2f patch\n", cputime());
	Bflush(&bso);
	mkfwd();
	s = lookup("exit", 0);
	vexit = s->value;
	for(p = firstp; p != P; p = p->link) {
		setarch(p);
		a = p->as;
		if(a == ATEXT)
			curtext = p;
		if(seenthumb && a == ABL){
			// if((s = p->to.sym) != S && (s1 = curtext->from.sym) != S)
			//	print("%s calls %s\n", s1->name, s->name);
			 if((s = p->to.sym) != S && (s1 = curtext->from.sym) != S && s->thumb != s1->thumb)
				s->foreign = 1;
		}
		if((a == ABL || a == ABX || a == AB || a == ARET) &&
		   p->to.type != D_BRANCH && p->to.sym != S) {
			s = p->to.sym;
			switch(s->type) {
			default:
				diag("undefined: %s", s->name);
				s->type = STEXT;
				s->value = vexit;
				continue;	// avoid more error messages
			case STEXT:
				p->to.offset = s->value;
				p->to.type = D_BRANCH;
				break;
			case SUNDEF:
				if(p->as != ABL)
					diag("help: SUNDEF in AB || ARET");
				p->to.offset = 0;
				p->to.type = D_BRANCH;
				p->cond = UP;
				break;
			}
		}
		if(p->to.type != D_BRANCH || p->cond == UP)
			continue;
		c = p->to.offset;
		for(q = firstp; q != P;) {
			if(q->forwd != P)
			if(c >= q->forwd->pc) {
				q = q->forwd;
				continue;
			}
			if(c == q->pc)
				break;
			q = q->link;
		}
		if(q == P) {
			diag("branch out of range %ld\n%P", c, p);
			p->to.type = D_NONE;
		}
		p->cond = q;
	}

	for(p = firstp; p != P; p = p->link) {
		setarch(p);
		a = p->as;
		if(p->as == ATEXT)
			curtext = p;
		if(seenthumb && a == ABL) {
#ifdef CALLEEBX
			if(0)
				{}
#else
			if((s = p->to.sym) != S && (s->foreign || s->fnptr))
				p->as = ABX;
#endif
			else if(p->to.type == D_OREG)
				p->as = ABX;
		}
		if(p->cond != P && p->cond != UP) {
			p->cond = brloop(p->cond);
			if(p->cond != P)
			if(p->to.type == D_BRANCH)
				p->to.offset = p->cond->pc;
		}
	}
}
Пример #4
0
void
patch(void)
{
    long c;
    Prog *p, *q;
    Sym *s;
    long vexit;

    if(debug['v'])
        Bprint(&bso, "%5.2f mkfwd\n", cputime());
    Bflush(&bso);
    mkfwd();
    if(debug['v'])
        Bprint(&bso, "%5.2f patch\n", cputime());
    Bflush(&bso);
    s = lookup("exit", 0);
    vexit = s->value;
    for(p = firstp; p != P; p = p->link) {
        if(p->as == ATEXT)
            curtext = p;
        if(p->as == ACALL || p->as == ARET) {
            s = p->to.sym;
            if(s) {
                if(debug['c'])
                    Bprint(&bso, "%s calls %s\n", TNAME, s->name);
                switch(s->type) {
                default:
                    /* diag prints TNAME first */
                    diag("undefined: %s", s->name);
                    s->type = STEXT;
                    s->value = vexit;
                    break;	/* or fall through to set offset? */
                case STEXT:
                    p->to.offset = s->value;
                    break;
                case SUNDEF:
                    p->pcond = UP;
                    p->to.offset = 0;
                    break;
                }
                p->to.type = D_BRANCH;
            }
        }
        if(p->to.type != D_BRANCH || p->pcond == UP)
            continue;
        c = p->to.offset;
        for(q = firstp; q != P;) {
            if(q->forwd != P)
                if(c >= q->forwd->pc) {
                    q = q->forwd;
                    continue;
                }
            if(c == q->pc)
                break;
            q = q->link;
        }
        if(q == P) {
            diag("branch out of range in %s\n%P", TNAME, p);
            p->to.type = D_NONE;
        }
        p->pcond = q;
    }

    for(p = firstp; p != P; p = p->link) {
        if(p->as == ATEXT)
            curtext = p;
        p->mark = 0;	/* initialization for follow */
        if(p->pcond != P && p->pcond != UP) {
            p->pcond = brloop(p->pcond);
            if(p->pcond != P)
                if(p->to.type == D_BRANCH)
                    p->to.offset = p->pcond->pc;
        }
    }
}
Пример #5
0
void
patch(void)
{
	int32 c;
	Prog *p, *q;
	Sym *s;
	int32 vexit;

	if(debug['v'])
		Bprint(&bso, "%5.2f mkfwd\n", cputime());
	Bflush(&bso);
	mkfwd();
	if(debug['v'])
		Bprint(&bso, "%5.2f patch\n", cputime());
	Bflush(&bso);

	s = lookup("exit", 0);
	vexit = s->value;
	for(cursym = textp; cursym != nil; cursym = cursym->next)
	for(p = cursym->text; p != P; p = p->link) {
		if(HEADTYPE == Hwindows) { 
			// Windows
			// Convert
			//   op	  n(GS), reg
			// to
			//   MOVL 0x28(GS), reg
			//   op	  n(reg), reg
			// The purpose of this patch is to fix some accesses
			// to extern register variables (TLS) on Windows, as
			// a different method is used to access them.
			if(p->from.type == D_INDIR+D_GS
			&& p->to.type >= D_AX && p->to.type <= D_DI 
			&& p->from.offset <= 8) {
				q = appendp(p);
				q->from = p->from;
				q->from.type = D_INDIR + p->to.type;
				q->to = p->to;
				q->as = p->as;
				p->as = AMOVQ;
				p->from.type = D_INDIR+D_GS;
				p->from.offset = 0x28;
			}
		}
		if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
		|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd) {
			// ELF uses FS instead of GS.
			if(p->from.type == D_INDIR+D_GS)
				p->from.type = D_INDIR+D_FS;
			if(p->to.type == D_INDIR+D_GS)
				p->to.type = D_INDIR+D_FS;
		}
		if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH)) {
			s = p->to.sym;
			if(s) {
				if(debug['c'])
					Bprint(&bso, "%s calls %s\n", TNAME, s->name);
				if((s->type&~SSUB) != STEXT) {
					/* diag prints TNAME first */
					diag("undefined: %s", s->name);
					s->type = STEXT;
					s->value = vexit;
					continue;	// avoid more error messages
				}
				if(s->text == nil)
					continue;
				p->to.type = D_BRANCH;
				p->to.offset = s->text->pc;
				p->pcond = s->text;
				continue;
			}
		}
		if(p->to.type != D_BRANCH)
			continue;
		c = p->to.offset;
		for(q = cursym->text; q != P;) {
			if(c == q->pc)
				break;
			if(q->forwd != P && c >= q->forwd->pc)
				q = q->forwd;
			else
				q = q->link;
		}
		if(q == P) {
			diag("branch out of range in %s (%#ux)\n%P [%s]",
				TNAME, c, p, p->to.sym ? p->to.sym->name : "<nil>");
			p->to.type = D_NONE;
		}
		p->pcond = q;
	}

	for(cursym = textp; cursym != nil; cursym = cursym->next)
	for(p = cursym->text; p != P; p = p->link) {
		p->mark = 0;	/* initialization for follow */
		if(p->pcond != P) {
			p->pcond = brloop(p->pcond);
			if(p->pcond != P)
			if(p->to.type == D_BRANCH)
				p->to.offset = p->pcond->pc;
		}
	}
}
Пример #6
0
void
patch(void)
{
	int32 c, vexit;
	Prog *p, *q;
	Sym *s;
	int a;

	if(debug['v'])
		Bprint(&bso, "%5.2f patch\n", cputime());
	Bflush(&bso);
	mkfwd();
	s = lookup("exit", 0);
	vexit = s->value;
	for(cursym = textp; cursym != nil; cursym = cursym->next) {
		for(p = cursym->text; p != P; p = p->link) {
			a = p->as;
			if((a == ABL || a == ABX || a == AB || a == ARET) &&
			   p->to.type != D_BRANCH && p->to.sym != S) {
				s = p->to.sym;
				if(s->text == nil)
					continue;
				switch(s->type&SMASK) {
				default:
					diag("undefined: %s", s->name);
					s->type = STEXT;
					s->value = vexit;
					continue;	// avoid more error messages
				case STEXT:
					p->to.offset = s->value;
					p->to.type = D_BRANCH;
					p->cond = s->text;
					continue;
				}
			}
			if(p->to.type != D_BRANCH)
				continue;
			c = p->to.offset;
			for(q = cursym->text; q != P;) {
				if(c == q->pc)
					break;
				if(q->forwd != P && c >= q->forwd->pc)
					q = q->forwd;
				else
					q = q->link;
			}
			if(q == P) {
				diag("branch out of range %d\n%P", c, p);
				p->to.type = D_NONE;
			}
			p->cond = q;
		}
	}

	for(cursym = textp; cursym != nil; cursym = cursym->next) {
		for(p = cursym->text; p != P; p = p->link) {
			if(p->cond != P) {
				p->cond = brloop(p->cond);
				if(p->cond != P)
				if(p->to.type == D_BRANCH)
					p->to.offset = p->cond->pc;
			}
		}
	}
}
Пример #7
0
void
patch(void)
{
	int32 c;
	Prog *p, *q;
	Sym *s, *gmsym;
	int32 vexit;

	if(debug['v'])
		Bprint(&bso, "%5.2f mkfwd\n", cputime());
	Bflush(&bso);
	mkfwd();
	if(debug['v'])
		Bprint(&bso, "%5.2f patch\n", cputime());
	Bflush(&bso);

	if(flag_shared) {
		s = lookup("init_array", 0);
		s->type = SINITARR;
		s->reachable = 1;
		s->hide = 1;
		addaddr(s, lookup(INITENTRY, 0));
	}

	gmsym = lookup("runtime.tlsgm", 0);
	if(linkmode != LinkExternal)
		gmsym->reachable = 0;
	s = lookup("exit", 0);
	vexit = s->value;
	for(cursym = textp; cursym != nil; cursym = cursym->next)
	for(p = cursym->text; p != P; p = p->link) {
		if(HEADTYPE == Hwindows) { 
			// Windows
			// Convert
			//   op	  n(GS), reg
			// to
			//   MOVL 0x28(GS), reg
			//   op	  n(reg), reg
			// The purpose of this patch is to fix some accesses
			// to extern register variables (TLS) on Windows, as
			// a different method is used to access them.
			if(p->from.type == D_INDIR+D_GS
			&& p->to.type >= D_AX && p->to.type <= D_DI 
			&& p->from.offset <= 8) {
				q = appendp(p);
				q->from = p->from;
				q->from.type = D_INDIR + p->to.type;
				q->to = p->to;
				q->as = p->as;
				p->as = AMOVQ;
				p->from.type = D_INDIR+D_GS;
				p->from.offset = 0x28;
			}
		}
		if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
		|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd
		|| HEADTYPE == Hplan9x64 || HEADTYPE == Hdragonfly) {
			// ELF uses FS instead of GS.
			if(p->from.type == D_INDIR+D_GS)
				p->from.type = D_INDIR+D_FS;
			if(p->to.type == D_INDIR+D_GS)
				p->to.type = D_INDIR+D_FS;
			if(p->from.index == D_GS)
				p->from.index = D_FS;
			if(p->to.index == D_GS)
				p->to.index = D_FS;
		}
		if(!flag_shared) {
			// Convert g() or m() accesses of the form
			//   op n(reg)(GS*1), reg
			// to
			//   op n(GS*1), reg
			if(p->from.index == D_FS || p->from.index == D_GS) {
				p->from.type = D_INDIR + p->from.index;
				p->from.index = D_NONE;
			}
			// Convert g() or m() accesses of the form
			//   op reg, n(reg)(GS*1)
			// to
			//   op reg, n(GS*1)
			if(p->to.index == D_FS || p->to.index == D_GS) {
				p->to.type = D_INDIR + p->to.index;
				p->to.index = D_NONE;
			}
			// Convert get_tls access of the form
			//   op runtime.tlsgm(SB), reg
			// to
			//   NOP
			if(gmsym != S && p->from.sym == gmsym) {
				p->as = ANOP;
				p->from.type = D_NONE;
				p->to.type = D_NONE;
				p->from.sym = nil;
				p->to.sym = nil;
				continue;
			}
		} else {
			// Convert TLS reads of the form
			//   op n(GS), reg
			// to
			//   MOVQ $runtime.tlsgm(SB), reg
			//   op n(reg)(GS*1), reg
			if((p->from.type == D_INDIR+D_FS || p->from.type == D_INDIR + D_GS) && p->to.type >= D_AX && p->to.type <= D_DI) {
				q = appendp(p);
				q->to = p->to;
				q->as = p->as;
				q->from.type = D_INDIR+p->to.type;
				q->from.index = p->from.type - D_INDIR;
				q->from.scale = 1;
				q->from.offset = p->from.offset;
				p->as = AMOVQ;
				p->from.type = D_EXTERN;
				p->from.sym = gmsym;
				p->from.offset = 0;
			}
		}
		if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH) || (p->as == ARET && p->to.sym != nil)) {
			s = p->to.sym;
			if(s) {
				if(debug['c'])
					Bprint(&bso, "%s calls %s\n", TNAME, s->name);
				if((s->type&SMASK) != STEXT) {
					/* diag prints TNAME first */
					diag("undefined: %s", s->name);
					s->type = STEXT;
					s->value = vexit;
					continue;	// avoid more error messages
				}
				if(s->text == nil)
					continue;
				p->to.type = D_BRANCH;
				p->to.offset = s->text->pc;
				p->pcond = s->text;
				continue;
			}
		}
		if(p->to.type != D_BRANCH)
			continue;
		c = p->to.offset;
		for(q = cursym->text; q != P;) {
			if(c == q->pc)
				break;
			if(q->forwd != P && c >= q->forwd->pc)
				q = q->forwd;
			else
				q = q->link;
		}
		if(q == P) {
			diag("branch out of range in %s (%#ux)\n%P [%s]",
				TNAME, c, p, p->to.sym ? p->to.sym->name : "<nil>");
			p->to.type = D_NONE;
		}
		p->pcond = q;
	}

	for(cursym = textp; cursym != nil; cursym = cursym->next)
	for(p = cursym->text; p != P; p = p->link) {
		p->mark = 0;	/* initialization for follow */
		if(p->pcond != P) {
			p->pcond = brloop(p->pcond);
			if(p->pcond != P)
			if(p->to.type == D_BRANCH)
				p->to.offset = p->pcond->pc;
		}
	}
}