head	1.72;
access;
symbols
	netbsd-11-0-RC5:1.72
	netbsd-11-0-RC4:1.72
	netbsd-11-0-RC3:1.72
	netbsd-11-0-RC2:1.72
	netbsd-11-0-RC1:1.72
	perseant-exfatfs-base-20250801:1.72
	netbsd-11:1.72.0.2
	netbsd-11-base:1.72
	netbsd-10-1-RELEASE:1.69.12.1
	perseant-exfatfs-base-20240630:1.70
	perseant-exfatfs:1.70.0.2
	perseant-exfatfs-base:1.70
	netbsd-8-3-RELEASE:1.59.6.2
	netbsd-9-4-RELEASE:1.69.4.1
	netbsd-10-0-RELEASE:1.69.12.1
	netbsd-10-0-RC6:1.69.12.1
	netbsd-10-0-RC5:1.69.12.1
	netbsd-10-0-RC4:1.69.12.1
	netbsd-10-0-RC3:1.69.12.1
	netbsd-10-0-RC2:1.69.12.1
	netbsd-10-0-RC1:1.69.12.1
	netbsd-10:1.69.0.12
	netbsd-10-base:1.69
	netbsd-9-3-RELEASE:1.69
	cjep_sun2x-base1:1.69
	cjep_sun2x:1.69.0.10
	cjep_sun2x-base:1.69
	cjep_staticlib_x-base1:1.69
	netbsd-9-2-RELEASE:1.69
	cjep_staticlib_x:1.69.0.8
	cjep_staticlib_x-base:1.69
	netbsd-9-1-RELEASE:1.69
	phil-wifi-20200421:1.69
	phil-wifi-20200411:1.69
	is-mlppp:1.69.0.6
	is-mlppp-base:1.69
	phil-wifi-20200406:1.69
	netbsd-8-2-RELEASE:1.59.6.2
	netbsd-9-0-RELEASE:1.69
	netbsd-9-0-RC2:1.69
	netbsd-9-0-RC1:1.69
	phil-wifi-20191119:1.69
	netbsd-9:1.69.0.4
	netbsd-9-base:1.69
	phil-wifi-20190609:1.69
	netbsd-8-1-RELEASE:1.59.6.2
	netbsd-8-1-RC1:1.59.6.2
	pgoyette-compat-merge-20190127:1.67.2.2
	pgoyette-compat-20190127:1.69
	pgoyette-compat-20190118:1.69
	pgoyette-compat-1226:1.69
	pgoyette-compat-1126:1.69
	pgoyette-compat-1020:1.69
	pgoyette-compat-0930:1.69
	pgoyette-compat-0906:1.69
	netbsd-7-2-RELEASE:1.56.4.1
	pgoyette-compat-0728:1.69
	netbsd-8-0-RELEASE:1.59.6.2
	phil-wifi:1.69.0.2
	phil-wifi-base:1.69
	pgoyette-compat-0625:1.69
	netbsd-8-0-RC2:1.59.6.2
	pgoyette-compat-0521:1.69
	pgoyette-compat-0502:1.69
	pgoyette-compat-0422:1.69
	netbsd-8-0-RC1:1.59.6.2
	pgoyette-compat-0415:1.69
	pgoyette-compat-0407:1.69
	pgoyette-compat-0330:1.68
	pgoyette-compat-0322:1.67
	pgoyette-compat-0315:1.67
	netbsd-7-1-2-RELEASE:1.56.4.1
	pgoyette-compat:1.67.0.2
	pgoyette-compat-base:1.67
	netbsd-7-1-1-RELEASE:1.56.4.1
	matt-nb8-mediatek:1.59.6.2.0.2
	matt-nb8-mediatek-base:1.59.6.2
	perseant-stdc-iso10646:1.61.0.2
	perseant-stdc-iso10646-base:1.61
	netbsd-8:1.59.0.6
	netbsd-8-base:1.59
	prg-localcount2-base3:1.59
	prg-localcount2-base2:1.59
	prg-localcount2-base1:1.59
	prg-localcount2:1.59.0.4
	prg-localcount2-base:1.59
	pgoyette-localcount-20170426:1.59
	bouyer-socketcan-base1:1.59
	pgoyette-localcount-20170320:1.59
	netbsd-7-1:1.56.4.1.0.4
	netbsd-7-1-RELEASE:1.56.4.1
	netbsd-7-1-RC2:1.56.4.1
	netbsd-7-nhusb-base-20170116:1.56.4.1
	bouyer-socketcan:1.59.0.2
	bouyer-socketcan-base:1.59
	pgoyette-localcount-20170107:1.59
	netbsd-7-1-RC1:1.56.4.1
	pgoyette-localcount-20161104:1.59
	netbsd-7-0-2-RELEASE:1.56
	localcount-20160914:1.59
	netbsd-7-nhusb:1.56.4.1.0.2
	netbsd-7-nhusb-base:1.56.4.1
	pgoyette-localcount-20160806:1.58
	pgoyette-localcount-20160726:1.58
	pgoyette-localcount:1.58.0.2
	pgoyette-localcount-base:1.58
	netbsd-7-0-1-RELEASE:1.56
	netbsd-7-0:1.56.0.6
	netbsd-7-0-RELEASE:1.56
	netbsd-7-0-RC3:1.56
	netbsd-7-0-RC2:1.56
	netbsd-7-0-RC1:1.56
	netbsd-5-2-3-RELEASE:1.43.4.1
	netbsd-5-1-5-RELEASE:1.43
	netbsd-6-0-6-RELEASE:1.52.6.1
	netbsd-6-1-5-RELEASE:1.52.6.1
	netbsd-7:1.56.0.4
	netbsd-7-base:1.56
	yamt-pagecache-base9:1.56
	yamt-pagecache-tag8:1.52.4.1
	netbsd-6-1-4-RELEASE:1.52.6.1
	netbsd-6-0-5-RELEASE:1.52.6.1
	tls-earlyentropy:1.56.0.2
	tls-earlyentropy-base:1.56
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.55
	riastradh-drm2-base3:1.55
	netbsd-6-1-3-RELEASE:1.52.6.1
	netbsd-6-0-4-RELEASE:1.52.6.1
	netbsd-5-2-2-RELEASE:1.43.4.1
	netbsd-5-1-4-RELEASE:1.43
	netbsd-6-1-2-RELEASE:1.52.6.1
	netbsd-6-0-3-RELEASE:1.52.6.1
	netbsd-5-2-1-RELEASE:1.43.4.1
	netbsd-5-1-3-RELEASE:1.43
	netbsd-6-1-1-RELEASE:1.52.6.1
	riastradh-drm2-base2:1.53
	riastradh-drm2-base1:1.53
	riastradh-drm2:1.53.0.4
	riastradh-drm2-base:1.53
	netbsd-6-1:1.52.6.1.0.6
	netbsd-6-0-2-RELEASE:1.52.6.1
	netbsd-6-1-RELEASE:1.52.6.1
	netbsd-6-1-RC4:1.52.6.1
	netbsd-6-1-RC3:1.52.6.1
	agc-symver:1.53.0.6
	agc-symver-base:1.53
	netbsd-6-1-RC2:1.52.6.1
	netbsd-6-1-RC1:1.52.6.1
	yamt-pagecache-base8:1.53
	netbsd-5-2:1.43.4.1.0.2
	netbsd-6-0-1-RELEASE:1.52.6.1
	yamt-pagecache-base7:1.53
	netbsd-5-2-RELEASE:1.43.4.1
	netbsd-5-2-RC1:1.43.4.1
	matt-nb6-plus-nbase:1.52.6.1
	yamt-pagecache-base6:1.53
	netbsd-6-0:1.52.6.1.0.4
	netbsd-6-0-RELEASE:1.52.6.1
	netbsd-6-0-RC2:1.52.6.1
	tls-maxphys:1.53.0.2
	tls-maxphys-base:1.56
	matt-nb6-plus:1.52.6.1.0.2
	matt-nb6-plus-base:1.52.6.1
	netbsd-6-0-RC1:1.52.6.1
	yamt-pagecache-base5:1.52
	yamt-pagecache-base4:1.52
	netbsd-6:1.52.0.6
	netbsd-6-base:1.52
	netbsd-5-1-2-RELEASE:1.43
	netbsd-5-1-1-RELEASE:1.43
	yamt-pagecache-base3:1.52
	yamt-pagecache-base2:1.52
	yamt-pagecache:1.52.0.4
	yamt-pagecache-base:1.52
	cherry-xenmp:1.52.0.2
	cherry-xenmp-base:1.52
	bouyer-quota2-nbase:1.50
	bouyer-quota2:1.50.0.2
	bouyer-quota2-base:1.50
	matt-mips64-premerge-20101231:1.50
	matt-nb5-mips64-premerge-20101231:1.43
	matt-nb5-pq3:1.43.0.14
	matt-nb5-pq3-base:1.43
	netbsd-5-1:1.43.0.12
	netbsd-5-1-RELEASE:1.43
	netbsd-5-1-RC4:1.43
	matt-nb5-mips64-k15:1.43
	netbsd-5-1-RC3:1.43
	netbsd-5-1-RC2:1.43
	netbsd-5-1-RC1:1.43
	netbsd-5-0-2-RELEASE:1.43
	matt-nb5-mips64-premerge-20091211:1.43
	matt-premerge-20091211:1.45
	matt-nb5-mips64-u2-k2-k4-k7-k8-k9:1.43
	matt-nb4-mips64-k7-u2a-k9b:1.43
	matt-nb5-mips64-u1-k1-k5:1.43
	matt-nb5-mips64:1.43.0.10
	netbsd-5-0-1-RELEASE:1.43
	jym-xensuspend-nbase:1.44
	netbsd-5-0:1.43.0.8
	netbsd-5-0-RELEASE:1.43
	netbsd-5-0-RC4:1.43
	netbsd-5-0-RC3:1.43
	netbsd-5-0-RC2:1.43
	jym-xensuspend:1.43.0.6
	jym-xensuspend-base:1.44
	netbsd-5-0-RC1:1.43
	netbsd-5:1.43.0.4
	netbsd-5-base:1.43
	matt-mips64-base2:1.43
	matt-mips64:1.41.0.12
	netbsd-4-0-1-RELEASE:1.39
	wrstuden-revivesa-base-3:1.43
	wrstuden-revivesa-base-2:1.43
	wrstuden-fixsa-newbase:1.39
	wrstuden-revivesa-base-1:1.42
	yamt-pf42-base4:1.42
	yamt-pf42-base3:1.42
	hpcarm-cleanup-nbase:1.42
	yamt-pf42-baseX:1.41
	yamt-pf42-base2:1.42
	wrstuden-revivesa:1.42.0.2
	wrstuden-revivesa-base:1.42
	yamt-pf42:1.41.0.10
	yamt-pf42-base:1.41
	keiichi-mipv6:1.41.0.8
	keiichi-mipv6-base:1.41
	matt-armv6-nbase:1.41
	matt-armv6-prevmlocking:1.41
	wrstuden-fixsa-base-1:1.39
	netbsd-4-0:1.39.0.8
	netbsd-4-0-RELEASE:1.39
	cube-autoconf:1.41.0.6
	cube-autoconf-base:1.41
	netbsd-4-0-RC5:1.39
	netbsd-4-0-RC4:1.39
	netbsd-4-0-RC3:1.39
	netbsd-4-0-RC2:1.39
	netbsd-4-0-RC1:1.39
	matt-armv6:1.41.0.4
	matt-armv6-base:1.41
	matt-mips64-base:1.41
	hpcarm-cleanup:1.41.0.2
	hpcarm-cleanup-base:1.41
	netbsd-3-1-1-RELEASE:1.35
	netbsd-3-0-3-RELEASE:1.35
	wrstuden-fixsa:1.39.0.6
	wrstuden-fixsa-base:1.39
	abandoned-netbsd-4-base:1.39
	abandoned-netbsd-4:1.39.0.2
	netbsd-3-1:1.35.0.6
	netbsd-3-1-RELEASE:1.35
	netbsd-3-0-2-RELEASE:1.35
	netbsd-3-1-RC4:1.35
	netbsd-3-1-RC3:1.35
	netbsd-3-1-RC2:1.35
	netbsd-3-1-RC1:1.35
	netbsd-4:1.39.0.4
	netbsd-4-base:1.39
	netbsd-3-0-1-RELEASE:1.35
	netbsd-3-0:1.35.0.4
	netbsd-3-0-RELEASE:1.35
	netbsd-3-0-RC6:1.35
	netbsd-3-0-RC5:1.35
	netbsd-3-0-RC4:1.35
	netbsd-3-0-RC3:1.35
	netbsd-3-0-RC2:1.35
	netbsd-3-0-RC1:1.35
	netbsd-2-0-3-RELEASE:1.34
	netbsd-2-1:1.34.0.6
	netbsd-2-1-RELEASE:1.34
	netbsd-2-1-RC6:1.34
	netbsd-2-1-RC5:1.34
	netbsd-2-1-RC4:1.34
	netbsd-2-1-RC3:1.34
	netbsd-2-1-RC2:1.34
	netbsd-2-1-RC1:1.34
	netbsd-2-0-2-RELEASE:1.34
	netbsd-3:1.35.0.2
	netbsd-3-base:1.35
	netbsd-2-0-1-RELEASE:1.34
	netbsd-2:1.34.0.4
	netbsd-2-base:1.34
	netbsd-2-0-RELEASE:1.34
	netbsd-2-0-RC5:1.34
	netbsd-2-0-RC4:1.34
	netbsd-2-0-RC3:1.34
	netbsd-2-0-RC2:1.34
	netbsd-2-0-RC1:1.34
	netbsd-2-0:1.34.0.2
	netbsd-2-0-base:1.34
	netbsd-1-6-PATCH002-RELEASE:1.5
	netbsd-1-6-PATCH002:1.5
	netbsd-1-6-PATCH002-RC4:1.5
	netbsd-1-6-PATCH002-RC3:1.5
	netbsd-1-6-PATCH002-RC2:1.5
	netbsd-1-6-PATCH002-RC1:1.5
	netbsd-1-6-PATCH001:1.5
	netbsd-1-6-PATCH001-RELEASE:1.5
	netbsd-1-6-PATCH001-RC3:1.5
	netbsd-1-6-PATCH001-RC2:1.5
	netbsd-1-6-PATCH001-RC1:1.5
	fvdl_fs64_base:1.32
	netbsd-1-6-RELEASE:1.5
	netbsd-1-6-RC3:1.5
	netbsd-1-6-RC2:1.5
	netbsd-1-6-RC1:1.5
	netbsd-1-6:1.5.0.2
	netbsd-1-6-base:1.5
	netbsd-1-5-PATCH003:1.3.2.4
	netbsd-1-5-PATCH002:1.3.2.3
	netbsd-1-5-PATCH001:1.3.2.3
	netbsd-1-5-RELEASE:1.3.2.2
	netbsd-1-5-BETA2:1.3.2.2
	netbsd-1-5-BETA:1.3.2.2
	netbsd-1-5-ALPHA2:1.3.2.2
	netbsd-1-5:1.3.0.2;
locks; strict;
comment	@ * @;


1.72
date	2024.08.03.21.59.58;	author riastradh;	state Exp;
branches;
next	1.71;
commitid	R5nq4VHUPO6kqqkF;

1.71
date	2024.07.23.09.55.19;	author uwe;	state Exp;
branches;
next	1.70;
commitid	V9jYcpP1BZIDLWiF;

1.70
date	2023.06.04.01.24.58;	author joerg;	state Exp;
branches
	1.70.2.1;
next	1.69;
commitid	jBAtDE6SYslzbzrE;

1.69
date	2018.04.03.21.10.27;	author joerg;	state Exp;
branches
	1.69.4.1
	1.69.12.1;
next	1.68;
commitid	pNUMy9CwSMm3w2xA;

1.68
date	2018.03.29.13.23.39;	author joerg;	state Exp;
branches;
next	1.67;
commitid	Kdf4QQLmYsiz5mwA;

1.67
date	2017.12.25.17.00.15;	author joerg;	state Exp;
branches
	1.67.2.1;
next	1.66;
commitid	FywyvRqFfTW8kikA;

1.66
date	2017.11.06.21.16.04;	author joerg;	state Exp;
branches;
next	1.65;
commitid	XwUFbplE2Hyqj1eA;

1.65
date	2017.08.12.09.03.27;	author joerg;	state Exp;
branches;
next	1.64;
commitid	CTtI1MJtBn9L1U2A;

1.64
date	2017.08.10.19.03.26;	author joerg;	state Exp;
branches;
next	1.63;
commitid	UgH5577k4GrjpH2A;

1.63
date	2017.07.24.08.08.34;	author martin;	state Exp;
branches;
next	1.62;
commitid	FKEfbH0bTV0Cks0A;

1.62
date	2017.07.23.14.37.51;	author martin;	state Exp;
branches;
next	1.61;
commitid	eGsEmTtizgYgwm0A;

1.61
date	2017.06.19.11.57.02;	author joerg;	state Exp;
branches;
next	1.60;
commitid	pYVYx1tH1kZmHYVz;

1.60
date	2017.06.15.23.10.12;	author joerg;	state Exp;
branches;
next	1.59;
commitid	RjfPIOu8uDGXzwVz;

1.59
date	2016.08.29.16.00.10;	author martin;	state Exp;
branches
	1.59.6.1;
next	1.58;
commitid	tckUBr8v1IaRvdkz;

1.58
date	2016.06.20.08.12.25;	author martin;	state Exp;
branches;
next	1.57;
commitid	kQJMgKIlQzp2bbbz;

1.57
date	2014.08.25.20.40.53;	author joerg;	state Exp;
branches;
next	1.56;
commitid	hm6gwLhn9YorHMNx;

1.56
date	2014.04.02.14.11.25;	author martin;	state Exp;
branches
	1.56.4.1;
next	1.55;
commitid	Yw8cERyZjxhdc7vx;

1.55
date	2013.10.03.10.45.57;	author martin;	state Exp;
branches;
next	1.54;
commitid	qTZH5mdfDsIsSP7x;

1.54
date	2013.09.23.21.00.35;	author martin;	state Exp;
branches;
next	1.53;
commitid	5gzgZdB4WdVHBB6x;

1.53
date	2012.07.22.09.21.03;	author martin;	state Exp;
branches
	1.53.2.1;
next	1.52;

1.52
date	2011.03.30.08.37.52;	author martin;	state Exp;
branches
	1.52.4.1
	1.52.6.1;
next	1.51;

1.51
date	2011.03.25.18.07.06;	author joerg;	state Exp;
branches;
next	1.50;

1.50
date	2010.09.24.12.00.10;	author skrll;	state Exp;
branches;
next	1.49;

1.49
date	2010.09.24.11.59.28;	author skrll;	state Exp;
branches;
next	1.48;

1.48
date	2010.09.24.11.57.11;	author skrll;	state Exp;
branches;
next	1.47;

1.47
date	2010.08.06.16.33.18;	author joerg;	state Exp;
branches;
next	1.46;

1.46
date	2010.01.13.20.17.22;	author christos;	state Exp;
branches;
next	1.45;

1.45
date	2009.05.22.21.47.46;	author martin;	state Exp;
branches;
next	1.44;

1.44
date	2009.03.16.02.46.48;	author lukem;	state Exp;
branches;
next	1.43;

1.43
date	2008.07.24.04.39.25;	author matt;	state Exp;
branches
	1.43.4.1
	1.43.6.1;
next	1.42;

1.42
date	2008.04.28.20.23.04;	author martin;	state Exp;
branches
	1.42.2.1;
next	1.41;

1.41
date	2007.02.23.01.17.11;	author matt;	state Exp;
branches
	1.41.10.1;
next	1.40;

1.40
date	2007.02.15.19.42.13;	author martin;	state Exp;
branches;
next	1.39;

1.39
date	2006.05.10.21.53.15;	author mrg;	state Exp;
branches;
next	1.38;

1.38
date	2005.12.24.20.59.31;	author perry;	state Exp;
branches;
next	1.37;

1.37
date	2005.08.20.19.01.17;	author skrll;	state Exp;
branches;
next	1.36;

1.36
date	2005.08.15.10.52.42;	author skrll;	state Exp;
branches;
next	1.35;

1.35
date	2005.01.05.09.16.03;	author martin;	state Exp;
branches;
next	1.34;

1.34
date	2003.07.24.10.12.29;	author skrll;	state Exp;
branches;
next	1.33;

1.33
date	2003.05.23.20.13.50;	author petrov;	state Exp;
branches;
next	1.32;

1.32
date	2002.10.18.20.35.25;	author thorpej;	state Exp;
branches;
next	1.31;

1.31
date	2002.09.26.20.42.12;	author mycroft;	state Exp;
branches;
next	1.30;

1.30
date	2002.09.26.02.25.57;	author mycroft;	state Exp;
branches;
next	1.29;

1.29
date	2002.09.26.02.14.10;	author mycroft;	state Exp;
branches;
next	1.28;

1.28
date	2002.09.25.22.29.12;	author mycroft;	state Exp;
branches;
next	1.27;

1.27
date	2002.09.25.22.25.11;	author mycroft;	state Exp;
branches;
next	1.26;

1.26
date	2002.09.25.16.35.08;	author mycroft;	state Exp;
branches;
next	1.25;

1.25
date	2002.09.25.14.36.37;	author mycroft;	state Exp;
branches;
next	1.24;

1.24
date	2002.09.25.14.35.39;	author mycroft;	state Exp;
branches;
next	1.23;

1.23
date	2002.09.25.07.27.54;	author mycroft;	state Exp;
branches;
next	1.22;

1.22
date	2002.09.24.13.59.31;	author mycroft;	state Exp;
branches;
next	1.21;

1.21
date	2002.09.12.22.56.31;	author mycroft;	state Exp;
branches;
next	1.20;

1.20
date	2002.09.12.20.24.03;	author mycroft;	state Exp;
branches;
next	1.19;

1.19
date	2002.09.12.20.21.01;	author mycroft;	state Exp;
branches;
next	1.18;

1.18
date	2002.09.11.19.46.41;	author mycroft;	state Exp;
branches;
next	1.17;

1.17
date	2002.09.06.15.51.24;	author mycroft;	state Exp;
branches;
next	1.16;

1.16
date	2002.09.06.15.32.57;	author mycroft;	state Exp;
branches;
next	1.15;

1.15
date	2002.09.06.15.17.59;	author mycroft;	state Exp;
branches;
next	1.14;

1.14
date	2002.09.06.03.12.08;	author mycroft;	state Exp;
branches;
next	1.13;

1.13
date	2002.09.06.03.05.37;	author mycroft;	state Exp;
branches;
next	1.12;

1.12
date	2002.09.06.02.01.40;	author mycroft;	state Exp;
branches;
next	1.11;

1.11
date	2002.09.05.21.31.35;	author mycroft;	state Exp;
branches;
next	1.10;

1.10
date	2002.09.05.21.21.12;	author mycroft;	state Exp;
branches;
next	1.9;

1.9
date	2002.09.05.20.08.19;	author mycroft;	state Exp;
branches;
next	1.8;

1.8
date	2002.09.05.18.25.47;	author mycroft;	state Exp;
branches;
next	1.7;

1.7
date	2002.09.05.16.33.58;	author junyoung;	state Exp;
branches;
next	1.6;

1.6
date	2002.09.05.15.38.31;	author mycroft;	state Exp;
branches;
next	1.5;

1.5
date	2001.04.25.12.24.51;	author kleink;	state Exp;
branches
	1.5.2.1;
next	1.4;

1.4
date	2000.09.16.14.04.30;	author eeh;	state Exp;
branches;
next	1.3;

1.3
date	2000.07.26.02.07.36;	author mycroft;	state Exp;
branches
	1.3.2.1;
next	1.2;

1.2
date	2000.07.18.22.33.56;	author eeh;	state Exp;
branches;
next	1.1;

1.1
date	2000.07.13.23.14.18;	author eeh;	state Exp;
branches;
next	;

1.70.2.1
date	2025.08.02.05.55.03;	author perseant;	state Exp;
branches;
next	;
commitid	23j6GFaDws3O875G;

1.69.4.1
date	2023.08.04.12.55.46;	author martin;	state Exp;
branches;
next	;
commitid	WQUk0iGBkKS39tzE;

1.69.12.1
date	2023.08.01.16.34.57;	author martin;	state Exp;
branches;
next	;
commitid	ygiHGMga8HEgs6zE;

1.67.2.1
date	2018.03.30.06.20.10;	author pgoyette;	state Exp;
branches;
next	1.67.2.2;
commitid	h5ZWTFXyqL8kJrwA;

1.67.2.2
date	2018.04.07.04.12.09;	author pgoyette;	state Exp;
branches;
next	;
commitid	ZMkKSYuBapz7LsxA;

1.59.6.1
date	2017.07.04.12.47.58;	author martin;	state Exp;
branches;
next	1.59.6.2;
commitid	WH1NGk1BGSqEwUXz;

1.59.6.2
date	2017.07.25.02.19.03;	author snj;	state Exp;
branches;
next	;
commitid	W9H15UHPCJjQmy0A;

1.56.4.1
date	2016.03.06.18.17.56;	author martin;	state Exp;
branches;
next	;
commitid	Ns3WeAQc8ORoVBXy;

1.53.2.1
date	2014.08.20.00.02.23;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.52.4.1
date	2012.10.30.18.59.23;	author yamt;	state Exp;
branches;
next	1.52.4.2;

1.52.4.2
date	2014.05.22.11.37.14;	author yamt;	state Exp;
branches;
next	;
commitid	VmckIax9CgOhKwBx;

1.52.6.1
date	2012.08.08.06.24.51;	author jdc;	state Exp;
branches;
next	;

1.43.4.1
date	2012.03.17.18.28.35;	author bouyer;	state Exp;
branches;
next	;

1.43.6.1
date	2009.05.13.19.18.42;	author jym;	state Exp;
branches;
next	;

1.42.2.1
date	2008.09.18.04.39.18;	author wrstuden;	state Exp;
branches;
next	;

1.41.10.1
date	2008.05.18.12.30.44;	author yamt;	state Exp;
branches;
next	;

1.5.2.1
date	2004.05.28.08.31.22;	author tron;	state Exp;
branches;
next	;

1.3.2.1
date	2000.07.26.02.07.36;	author mycroft;	state dead;
branches;
next	1.3.2.2;

1.3.2.2
date	2000.07.26.23.45.23;	author mycroft;	state Exp;
branches;
next	1.3.2.3;

1.3.2.3
date	2001.05.01.12.07.23;	author he;	state Exp;
branches;
next	1.3.2.4;

1.3.2.4
date	2001.12.09.17.23.30;	author he;	state Exp;
branches;
next	;


desc
@@


1.72
log
@ld.elf_so(1): Nix trailing whitespace.

No functional change intended.
@
text
@/*	$NetBSD: mdreloc.c,v 1.71 2024/07/23 09:55:19 uwe Exp $	*/

/*-
 * Copyright (c) 2000 Eduardo Horvath.
 * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Paul Kranenburg and by Charles M. Hannum.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * SPARC ELF relocations.
 *
 * Reference:
 *
 *	SPARC Compliance Definition 2.4.1
 *	http://sparc.org/wp-content/uploads/2014/01/SCD.2.4.1.pdf.gz
 */

#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.71 2024/07/23 09:55:19 uwe Exp $");
#endif /* not lint */

#include <machine/elf_support.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "rtldenv.h"
#include "debug.h"
#include "rtld.h"

/*
 * The following table holds for each relocation type:
 *	- the width in bits of the memory location the relocation
 *	  applies to (not currently used)
 *	- the number of bits the relocation value must be shifted to the
 *	  right (i.e. discard least significant bits) to fit into
 *	  the appropriate field in the instruction word.
 *	- flags indicating whether
 *		* the relocation involves a symbol
 *		* the relocation is relative to the current position
 *		* the relocation is for a GOT entry
 *		* the relocation is relative to the load address
 *
 */
#define _RF_S		0x80000000		/* Resolve symbol */
#define _RF_A		0x40000000		/* Use addend */
#define _RF_P		0x20000000		/* Location relative */
#define _RF_G		0x10000000		/* GOT offset */
#define _RF_B		0x08000000		/* Load address relative */
#define _RF_U		0x04000000		/* Unaligned */
#define _RF_SZ(s)	(((s) & 0xff) << 8)	/* memory target size */
#define _RF_RS(s)	( (s) & 0xff)		/* right shift */
static const int reloc_target_flags[R_TYPE(TLS_TPOFF64)+1] = {
	0,							/* NONE */
	_RF_S|_RF_A|		_RF_SZ(8)  | _RF_RS(0),		/* RELOC_8 */
	_RF_S|_RF_A|		_RF_SZ(16) | _RF_RS(0),		/* RELOC_16 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* RELOC_32 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(8)  | _RF_RS(0),		/* DISP_8 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(16) | _RF_RS(0),		/* DISP_16 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* DISP_32 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP_30 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP_22 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(10),	/* HI22 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 22 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 13 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* LO10 */
	_RF_G|			_RF_SZ(32) | _RF_RS(0),		/* GOT10 */
	_RF_G|			_RF_SZ(32) | _RF_RS(0),		/* GOT13 */
	_RF_G|			_RF_SZ(32) | _RF_RS(10),	/* GOT22 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* PC10 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(10),	/* PC22 */
	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WPLT30 */
				_RF_SZ(32) | _RF_RS(0),		/* COPY */
	_RF_S|_RF_A|		_RF_SZ(64) | _RF_RS(0),		/* GLOB_DAT */
				_RF_SZ(32) | _RF_RS(0),		/* JMP_SLOT */
	      _RF_A|	_RF_B|	_RF_SZ(64) | _RF_RS(0),		/* RELATIVE */
	_RF_S|_RF_A|	_RF_U|	_RF_SZ(32) | _RF_RS(0),		/* UA_32 */

	      _RF_A|		_RF_SZ(32) | _RF_RS(0),		/* PLT32 */
	      _RF_A|		_RF_SZ(32) | _RF_RS(10),	/* HIPLT22 */
	      _RF_A|		_RF_SZ(32) | _RF_RS(0),		/* LOPLT10 */
	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* PCPLT32 */
	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(10),	/* PCPLT22 */
	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* PCPLT10 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 10 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 11 */
	_RF_S|_RF_A|		_RF_SZ(64) | _RF_RS(0),		/* 64 */
	_RF_S|_RF_A|/*extra*/	_RF_SZ(32) | _RF_RS(0),		/* OLO10 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(42),	/* HH22 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(32),	/* HM10 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(10),	/* LM22 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(42),	/* PC_HH22 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(32),	/* PC_HM10 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(10),	/* PC_LM22 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP16 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP19 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* GLOB_JMP */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 7 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 5 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 6 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(64) | _RF_RS(0),		/* DISP64 */
	      _RF_A|		_RF_SZ(64) | _RF_RS(0),		/* PLT64 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(10),	/* HIX22 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* LOX10 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(22),	/* H44 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(12),	/* M44 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* L44 */
	_RF_S|_RF_A|		_RF_SZ(64) | _RF_RS(0),		/* REGISTER */
	_RF_S|_RF_A|	_RF_U|	_RF_SZ(64) | _RF_RS(0),		/* UA64 */
	_RF_S|_RF_A|	_RF_U|	_RF_SZ(16) | _RF_RS(0),		/* UA16 */
/* TLS relocs not represented here! */
};

#ifdef RTLD_DEBUG_RELOC
static const char *reloc_names[] = {
	"NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8",
	"DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22",
	"22", "13", "LO10", "GOT10", "GOT13",
	"GOT22", "PC10", "PC22", "WPLT30", "COPY",
	"GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32", "PLT32",
	"HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", "PCPLT32",
	"10", "11", "64", "OLO10", "HH22",
	"HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22",
	"WDISP16", "WDISP19", "GLOB_JMP", "7", "5", "6",
	"DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44",
	"L44", "REGISTER", "UA64", "UA16",
	"TLS_GD_HI22", "TLS_GD_LO10", "TLS_GD_ADD", "TLS_GD_CALL",
	"TLS_LDM_HI22", "TLS_LDM_LO10", "TLS_LDM_ADD", "TLS_LDM_CALL",
	"TLS_LDO_HIX22", "TLS_LDO_LOX10", "TLS_LDO_ADD", "TLS_IE_HI22",
	"TLS_IE_LO10", "TLS_IE_LD", "TLS_IE_LDX", "TLS_IE_ADD", "TLS_LE_HIX22",
	"TLS_LE_LOX10", "TLS_DTPMOD32", "TLS_DTPMOD64", "TLS_DTPOFF32",
	"TLS_DTPOFF64", "TLS_TPOFF32", "TLS_TPOFF64",
};
#endif

#define RELOC_RESOLVE_SYMBOL(t)		((reloc_target_flags[t] & _RF_S) != 0)
#define RELOC_PC_RELATIVE(t)		((reloc_target_flags[t] & _RF_P) != 0)
#define RELOC_BASE_RELATIVE(t)		((reloc_target_flags[t] & _RF_B) != 0)
#define RELOC_UNALIGNED(t)		((reloc_target_flags[t] & _RF_U) != 0)
#define RELOC_USE_ADDEND(t)		((reloc_target_flags[t] & _RF_A) != 0)
#define RELOC_TARGET_SIZE(t)		((reloc_target_flags[t] >> 8) & 0xff)
#define RELOC_VALUE_RIGHTSHIFT(t)	(reloc_target_flags[t] & 0xff)
#define RELOC_TLS(t)			(t >= R_TYPE(TLS_GD_HI22))

static const long reloc_target_bitmask[] = {
#define _BM(x)	(~(-(1ULL << (x))))
	0,				/* NONE */
	_BM(8), _BM(16), _BM(32),	/* RELOC_8, _16, _32 */
	_BM(8), _BM(16), _BM(32),	/* DISP8, DISP16, DISP32 */
	_BM(30), _BM(22),		/* WDISP30, WDISP22 */
	_BM(22), _BM(22),		/* HI22, _22 */
	_BM(13), _BM(10),		/* RELOC_13, _LO10 */
	_BM(10), _BM(13), _BM(22),	/* GOT10, GOT13, GOT22 */
	_BM(10), _BM(22),		/* _PC10, _PC22 */
	_BM(30), 0,			/* _WPLT30, _COPY */
	-1, _BM(32), -1,		/* _GLOB_DAT, JMP_SLOT, _RELATIVE */
	_BM(32), _BM(32),		/* _UA32, PLT32 */
	_BM(22), _BM(10),		/* _HIPLT22, LOPLT10 */
	_BM(32), _BM(22), _BM(10),	/* _PCPLT32, _PCPLT22, _PCPLT10 */
	_BM(10), _BM(11), -1,		/* _10, _11, _64 */
	_BM(13), _BM(22),		/* _OLO10, _HH22 */
	_BM(10), _BM(22),		/* _HM10, _LM22 */
	_BM(22), _BM(10), _BM(22),	/* _PC_HH22, _PC_HM10, _PC_LM22 */
	_BM(16), _BM(19),		/* _WDISP16, _WDISP19 */
	-1,				/* GLOB_JMP */
	_BM(7), _BM(5), _BM(6),		/* _7, _5, _6 */
	-1, -1,				/* DISP64, PLT64 */
	_BM(22), _BM(13),		/* HIX22, LOX10 */
	_BM(22), _BM(10), _BM(12),	/* H44, M44, L44 */
	-1, -1, _BM(16),		/* REGISTER, UA64, UA16 */
#undef _BM
};
#define RELOC_VALUE_BITMASK(t)	(reloc_target_bitmask[t])

/*
 * Instruction templates:
 */


/* %hi(v)/%lo(v) with variable shift */
#define	HIVAL(v, s)	(((v) >> (s)) & 0x003fffff)
#define LOVAL(v, s)	(((v) >> (s)) & 0x000003ff)

void _rtld_bind_start_0(long, long);
void _rtld_bind_start_1(long, long);
void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);

/*
 * Install rtld function call into this PLT slot.
 */
#define	SAVE		0x9de3bf50	/* i.e. `save %sp,-176,%sp' */
#define	SETHI_l0	0x21000000
#define	SETHI_l1	0x23000000
#define	OR_l0_l0	0xa0142000
#define	SLLX_l0_32_l0	0xa12c3020
#define	OR_l0_l1_l0	0xa0140011
#define	JMPL_l0_o0	0x91c42000
#define	MOV_g1_o1	0x92100001

void _rtld_install_plt(Elf_Word *, Elf_Addr);
static inline int _rtld_relocate_plt_object(const Obj_Entry *,
    const Elf_Rela *, Elf_Addr *);

void
_rtld_install_plt(Elf_Word *pltgot, Elf_Addr proc)
{
	pltgot[0] = SAVE;
	pltgot[1] = SETHI_l0  | HIVAL(proc, 42);
	pltgot[2] = SETHI_l1  | HIVAL(proc, 10);
	pltgot[3] = OR_l0_l0  | LOVAL(proc, 32);
	pltgot[4] = SLLX_l0_32_l0;
	pltgot[5] = OR_l0_l1_l0;
	pltgot[6] = JMPL_l0_o0 | LOVAL(proc, 0);
	pltgot[7] = MOV_g1_o1;
}

void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
	/*
	 * On sparc64 we got troubles.
	 *
	 * Instructions are 4 bytes long.
	 * Elf[64]_Addr is 8 bytes long, so are our pltglot[]
	 * array entries.
	 * Each PLT entry jumps to PLT0 to enter the dynamic
	 * linker.
	 * Loading an arbitrary 64-bit pointer takes 6
	 * instructions and 2 registers.
	 *
	 * Somehow we need to issue a save to get a new stack
	 * frame, load the address of the dynamic linker, and
	 * jump there, in 8 instructions or less.
	 *
	 * Oh, we need to fill out both PLT0 and PLT1.
	 */
	{
		Elf_Word *entry = (Elf_Word *)obj->pltgot;

		/* Install in entries 0 and 1 */
		_rtld_install_plt(&entry[0], (Elf_Addr) &_rtld_bind_start_0);
		_rtld_install_plt(&entry[8], (Elf_Addr) &_rtld_bind_start_1);

		/*
		 * Install the object reference in first slot
		 * of entry 2.
		 */
		obj->pltgot[8] = (Elf_Addr) obj;
	}
}

void
_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
{
	const Elf_Rela *rela = 0, *relalim;
	Elf_Addr relasz = 0;
	Elf_Addr *where;

	for (; dynp->d_tag != DT_NULL; dynp++) {
		switch (dynp->d_tag) {
		case DT_RELA:
			rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
			break;
		case DT_RELASZ:
			relasz = dynp->d_un.d_val;
			break;
		}
	}
	relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
	for (; rela < relalim; rela++) {
		where = (Elf_Addr *)(relocbase + rela->r_offset);
		*where = (Elf_Addr)(relocbase + rela->r_addend);
	}
}

int
_rtld_relocate_nonplt_objects(Obj_Entry *obj)
{
	const Elf_Rela *rela;
	const Elf_Sym *def = NULL;
	const Obj_Entry *defobj = NULL;
	unsigned long last_symnum = ULONG_MAX;

	for (rela = obj->rela; rela < obj->relalim; rela++) {
		Elf_Addr *where;
		Elf_Word type;
		Elf_Addr value = 0, mask;
		unsigned long symnum;

		where = (Elf_Addr *) (obj->relocbase + rela->r_offset);

		type = ELF_R_TYPE(rela->r_info);
		if (type == R_TYPE(NONE))
			continue;

		/* OLO10 relocations have extra info */
		if ((type & 0x00ff) == R_SPARC_OLO10)
			type = R_SPARC_OLO10;

		/* We do JMP_SLOTs in _rtld_bind() below */
		if (type == R_TYPE(JMP_SLOT))
			continue;

		/* IFUNC relocations are handled in _rtld_call_ifunc */
		if (type == R_TYPE(IRELATIVE)) {
			if (obj->ifunc_remaining_nonplt == 0) {
				obj->ifunc_remaining_nonplt =
				    obj->relalim - rela;
			}
			continue;
		}

		/* COPY relocs are also handled elsewhere */
		if (type == R_TYPE(COPY))
			continue;

		/*
		 * We use the fact that relocation types are an `enum'
		 * Note: R_SPARC_TLS_TPOFF64 is currently numerically largest.
		 */
		if (type > R_TYPE(TLS_TPOFF64)) {
			dbg(("unknown relocation type %x at %p", type, rela));
			return -1;
		}

		value = rela->r_addend;

		if (RELOC_RESOLVE_SYMBOL(type) || RELOC_TLS(type)) {
			symnum = ELF_R_SYM(rela->r_info);
			if (last_symnum != symnum) {
				last_symnum = symnum;
				def = _rtld_find_symdef(symnum, obj, &defobj,
				    false);
				if (def == NULL)
					return -1;
			}
		}

		/*
		 * Handle TLS relocations here, they are different.
		 */
		if (RELOC_TLS(type)) {
			switch (type) {
			case R_TYPE(TLS_DTPMOD64):
				*where = (Elf64_Addr)defobj->tlsindex;

				rdbg(("TLS_DTPMOD64 %s in %s --> %p",
				    obj->strtab +
				    obj->symtab[symnum].st_name,
				    obj->path, (void *)*where));

				break;

			case R_TYPE(TLS_DTPOFF64):
				*where = (Elf64_Addr)(def->st_value
				    + rela->r_addend);

				rdbg(("DTPOFF64 %s in %s --> %p",
				    obj->strtab +
				        obj->symtab[symnum].st_name,
				    obj->path, (void *)*where));

				break;

			case R_TYPE(TLS_TPOFF64):
				if (!defobj->tls_static &&
				    _rtld_tls_offset_allocate(__UNCONST(defobj)))
					return -1;

				*where = (Elf64_Addr)(def->st_value -
				    defobj->tlsoffset + rela->r_addend);

				rdbg(("TLS_TPOFF64 %s in %s --> %p",
				    obj->strtab + obj->symtab[symnum].st_name,
				    obj->path, (void *)*where));

				break;
			}
			continue;
		}

		/*
		 * Handle relative relocs here, as an optimization.
		 */
		if (type == R_TYPE(RELATIVE)) {
			*where = (Elf_Addr)(obj->relocbase + value);
			rdbg(("RELATIVE in %s --> %p", obj->path,
			    (void *)*where));
			continue;
		}

		if (RELOC_RESOLVE_SYMBOL(type)) {
			/* Add in the symbol's absolute address */
			value += (Elf_Addr)(defobj->relocbase + def->st_value);
		}

		if (type == R_SPARC_OLO10) {
			value = (value & 0x3ff)
			    + (((Elf64_Xword)rela->r_info<<32)>>40);
		}

		if (RELOC_PC_RELATIVE(type)) {
			value -= (Elf_Addr)where;
		}

		if (RELOC_BASE_RELATIVE(type)) {
			/*
			 * Note that even though sparcs use `Elf_rela'
			 * exclusively we still need the implicit memory addend
			 * in relocations referring to GOT entries.
			 * Undoubtedly, someone f*cked this up in the distant
			 * past, and now we're stuck with it in the name of
			 * compatibility for all eternity..
			 *
			 * In any case, the implicit and explicit should be
			 * mutually exclusive. We provide a check for that
			 * here.
			 */
#ifdef DIAGNOSTIC
			if (value != 0 && *where != 0) {
				xprintf("BASE_REL(%s): where=%p, *where 0x%lx, "
					"addend=0x%lx, base %p\n",
					obj->path, where, *where,
					rela->r_addend, obj->relocbase);
			}
#endif
			/* XXXX -- apparently we ignore the preexisting value */
			value += (Elf_Addr)(obj->relocbase);
		}

		mask = RELOC_VALUE_BITMASK(type);
		value >>= RELOC_VALUE_RIGHTSHIFT(type);
		value &= mask;

		if (RELOC_UNALIGNED(type)) {
			/* Handle unaligned relocations. */
			Elf_Addr tmp = 0;
			char *ptr = (char *)where;
			int i, size = RELOC_TARGET_SIZE(type)/8;

			/* Read it in one byte at a time. */
			for (i=0; i<size; i++)
				tmp = (tmp << 8) | ptr[i];

			tmp &= ~mask;
			tmp |= value;

			/* Write it back out. */
			for (i=0; i<size; i++)
				ptr[i] = ((tmp >> (8*i)) & 0xff);
#ifdef RTLD_DEBUG_RELOC
			value = (Elf_Addr)tmp;
#endif

		} else if (RELOC_TARGET_SIZE(type) > 32) {
			*where &= ~mask;
			*where |= value;
#ifdef RTLD_DEBUG_RELOC
			value = (Elf_Addr)*where;
#endif
		} else {
			Elf32_Addr *where32 = (Elf32_Addr *)where;

			*where32 &= ~mask;
			*where32 |= value;
#ifdef RTLD_DEBUG_RELOC
			value = (Elf_Addr)*where32;
#endif
		}

#ifdef RTLD_DEBUG_RELOC
		if (RELOC_RESOLVE_SYMBOL(type)) {
			rdbg(("%s %s in %s --> %p in %s", reloc_names[type],
			    obj->strtab + obj->symtab[symnum].st_name,
			    obj->path, (void *)value, defobj->path));
		} else {
			rdbg(("%s in %s --> %p", reloc_names[type],
			    obj->path, (void *)value));
		}
#endif
	}
	return (0);
}

int
_rtld_relocate_plt_lazy(Obj_Entry *obj)
{
	const Elf_Rela *rela;

	for (rela = obj->pltrelalim; rela-- > obj->pltrela; ) {
		if (ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_IREL))
			obj->ifunc_remaining = obj->pltrelalim - rela + 1;
	}

	return 0;
}

caddr_t
_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
{
	const Elf_Rela *rela = obj->pltrela + reloff;
	Elf_Addr result;
	int err;

	result = 0;	/* XXX gcc */

	if (ELF_R_TYPE(obj->pltrela->r_info) == R_TYPE(JMP_SLOT) ||
	    ELF_R_TYPE(obj->pltrela->r_info) == R_TYPE(JMP_IREL)) {
		/*
		 * XXXX
		 *
		 * The first four PLT entries are reserved.  There is some
		 * disagreement whether they should have associated relocation
		 * entries.  Both the SPARC 32-bit and 64-bit ELF
		 * specifications say that they should have relocation entries,
		 * but the 32-bit SPARC binutils do not generate them, and now
		 * the 64-bit SPARC binutils have stopped generating them too.
		 *
		 * So, to provide binary compatibility, we will check the first
		 * entry, if it is reserved it should not be of the type
		 * JMP_SLOT or JMP_REL.  If it is either of those, then
		 * the 4 reserved entries were not generated and our index
		 * is 4 entries too far.
		 */
		rela -= 4;
	}

	_rtld_shared_enter();
	err = _rtld_relocate_plt_object(obj, rela, &result);
	if (err)
		_rtld_die();
	_rtld_shared_exit();

	return (caddr_t)result;
}

int
_rtld_relocate_plt_objects(const Obj_Entry *obj)
{
	const Elf_Rela *rela;

	rela = obj->pltrela;

	/*
	 * Check for first four reserved entries - and skip them.
	 * See above for details.
	 */
	if (ELF_R_TYPE(obj->pltrela->r_info) != R_TYPE(JMP_SLOT) &&
	    ELF_R_TYPE(obj->pltrela->r_info) != R_TYPE(JMP_IREL))
		rela += 4;

	for (; rela < obj->pltrelalim; rela++)
		if (_rtld_relocate_plt_object(obj, rela, NULL) < 0)
			return -1;

	return 0;
}

static inline void
_rtld_write_plt(Elf_Word *where, Elf_Addr value, const Elf_Rela *rela,
    const Obj_Entry *obj)
{
	if (rela && rela->r_addend) {
		Elf_Addr *ptr = (Elf_Addr *)where;
		/*
		 * This entry is >= 32768.  The relocations points to a
		 * PC-relative pointer to the bind_0 stub at the top of the
		 * PLT section.  Update it to point to the target function.
		 */
		ptr[0] += value - (Elf_Addr)obj->pltgot;
	} else {
		sparc_write_branch(where + 1, (void *)value);
	}
}

/*
 * New inline function that is called by _rtld_relocate_plt_object and
 * _rtld_bind
 */
static inline int
_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
    Elf_Addr *tp)
{
	Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
	const Elf_Sym *def;
	const Obj_Entry *defobj;
	Elf_Addr value;
	unsigned long info = rela->r_info;

	if (ELF_R_TYPE(info) == R_TYPE(JMP_IREL))
		return 0;

	assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));

	def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
	if (__predict_false(def == NULL))
		return -1;
	if (__predict_false(def == &_rtld_sym_zero))
		return 0;

	if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
		if (tp == NULL)
			return 0;
		value = _rtld_resolve_ifunc(defobj, def);
	} else {
		value = (Elf_Addr)(defobj->relocbase + def->st_value);
	}
	rdbg(("bind now/fixup in %s at %p --> new=%p",
	    defobj->strtab + def->st_name, (void*)where, (void *)value));

	_rtld_write_plt(where, value, rela, obj);

	if (tp)
		*tp = value;

	return 0;
}
@


1.71
log
@ld.elf_so: Cite reference for SPARC ELF relocations

PR lib/58455: Missing references for processor-specific ELF
relocation semantics
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.70 2023/06/04 01:24:58 joerg Exp $	*/
d44 1
a44 1
__RCSID("$NetBSD: mdreloc.c,v 1.70 2023/06/04 01:24:58 joerg Exp $");
d151 1
a151 1
	"HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22", 
d153 1
a153 1
	"DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44", 
d157 3
a159 3
	"TLS_LDO_HIX22", "TLS_LDO_LOX10", "TLS_LDO_ADD", "TLS_IE_HI22", 
	"TLS_IE_LO10", "TLS_IE_LD", "TLS_IE_LDX", "TLS_IE_ADD", "TLS_LE_HIX22", 
	"TLS_LE_LOX10", "TLS_DTPMOD32", "TLS_DTPMOD64", "TLS_DTPOFF32", 
d182 1
a182 1
	_BM(10), _BM(22),		/* _PC10, _PC22 */  
d273 1
a273 1
		/* 
d547 1
a547 1
		 * 
d637 1
a637 1
	rdbg(("bind now/fixup in %s at %p --> new=%p", 
@


1.70
log
@Fix interactions of initial-exec TLS model and dlopen

(1) If an initial-exec relocation was used for a non-local symbol
(i.e. the definition of the symbol is in a different DSO), the
computation of the static TLS offset used the wrong DSO.
This would effectively mean the wrong address was computed
(PR toolchain/50277, PR pkg/57445).

Fix this by forcing the computation of the correct DSO (the one defining
the symbol).

This code uses __UNCONST to avoid the vast interface changes for this
special case.

(2) If symbols from a DSO loaded via dlopen are used with both
global-dynamic/local-dynamic and initial-exec relocations AND
a initial-exec relocation was resolved first in a thread, a split brain
situation could exist where the dynamic relocations would use one memory
block (separate allocation) and the initial-exec relocations the static
per-thread TLS space.

(3) If the initial-exec relocation in (2) is seen after any thread has
already used a GD/LD allocation, bail out. Since IE relocations are used
only in the GOT, this will prevent the dlopen. This is a bit more
aggressive than necessary, but a full blown reference counting doesn't
seem to be justified.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.69 2018/04/03 21:10:27 joerg Exp $	*/
d33 9
d44 1
a44 1
__RCSID("$NetBSD: mdreloc.c,v 1.69 2018/04/03 21:10:27 joerg Exp $");
@


1.70.2.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.72 2024/08/03 21:59:58 riastradh Exp $	*/
a32 9
/*
 * SPARC ELF relocations.
 *
 * Reference:
 *
 *	SPARC Compliance Definition 2.4.1
 *	http://sparc.org/wp-content/uploads/2014/01/SCD.2.4.1.pdf.gz
 */

d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.72 2024/08/03 21:59:58 riastradh Exp $");
d142 1
a142 1
	"HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22",
d144 1
a144 1
	"DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44",
d148 3
a150 3
	"TLS_LDO_HIX22", "TLS_LDO_LOX10", "TLS_LDO_ADD", "TLS_IE_HI22",
	"TLS_IE_LO10", "TLS_IE_LD", "TLS_IE_LDX", "TLS_IE_ADD", "TLS_LE_HIX22",
	"TLS_LE_LOX10", "TLS_DTPMOD32", "TLS_DTPMOD64", "TLS_DTPOFF32",
d173 1
a173 1
	_BM(10), _BM(22),		/* _PC10, _PC22 */
d264 1
a264 1
		/*
d538 1
a538 1
		 *
d628 1
a628 1
	rdbg(("bind now/fixup in %s at %p --> new=%p",
@


1.69
log
@Rework ifunc support to address a number of short comings:
- Move to a shared _rtld_call_ifunc for rel and rela architectures
- Architectures using rel format must patch IRELATIVE non-PLT
  relocations like RELATIVE in additition to the later ifunc handling
- Consistently record the delta to the end of the relocation group for
  non-PLT IRELATIVE relocations

Hidden ifunc is now supported on all ifunc platforms, even when using
-fno-plt. The combination of -fno-plt and relro is broken due to
incorrect GNU ld output though.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.68 2018/03/29 13:23:39 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.68 2018/03/29 13:23:39 joerg Exp $");
d386 3
a388 3
				if (!defobj->tls_done &&
					_rtld_tls_offset_allocate(obj))
					     return -1;
@


1.69.4.1
log
@Pull up following revision(s), all via patch,
(requested by riastradh in ticket #1699):

	distrib/sets/lists/tests/shl.mi: revision 1.14
	distrib/sets/lists/tests/shl.mi: revision 1.15
	distrib/sets/lists/tests/shl.mi: revision 1.16
	tests/libexec/ld.elf_so/helper_def_static/h_def_static.c: revision 1.1
	tests/libexec/ld.elf_so/helper_def_dynamic/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_def_dynamic/Makefile: revision 1.2
	tests/libexec/ld.elf_so/helper_onlyuse_static/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_onlyuse_static/Makefile: revision 1.2
	libexec/ld.elf_so/arch/mips/mips_reloc.c: revision 1.75
	distrib/sets/lists/tests/mi: revision 1.1265
	libexec/ld.elf_so/arch/sh3/mdreloc.c: revision 1.36
	libexec/ld.elf_so/rtld.c: revision 1.214
	tests/libexec/ld.elf_so/helper_onlydef_static/Makefile: revision 1.1
	distrib/sets/lists/debug/mi: revision 1.400
	tests/libexec/ld.elf_so/helper_onlydef_static/Makefile: revision 1.2
	distrib/sets/lists/debug/mi: revision 1.401
	distrib/sets/lists/debug/mi: revision 1.402
	tests/libexec/ld.elf_so/helper_dso2/Makefile: revision 1.2
	distrib/sets/lists/debug/mi: revision 1.403
	tests/libexec/ld.elf_so/helper_symver_dso0/Makefile: revision 1.2
	libexec/ld.elf_so/arch/x86_64/mdreloc.c: revision 1.48
	distrib/sets/lists/debug/mi: revision 1.406
	tests/libexec/ld.elf_so/helper_use_dynamic/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_use_dynamic/Makefile: revision 1.2
	tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile: revision 1.2
	libexec/ld.elf_so/arch/sparc64/mdreloc.c: revision 1.70
	libexec/ld.elf_so/arch/aarch64/mdreloc.c: revision 1.18
	tests/libexec/ld.elf_so/helper_abuse_dynamic/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_abuse_dynamic/Makefile: revision 1.2
	tests/libexec/ld.elf_so/Makefile: revision 1.13
	libexec/ld.elf_so/arch/arm/mdreloc.c: revision 1.46
	libexec/ld.elf_so/rtld.h: revision 1.146
	tests/libexec/ld.elf_so/Makefile: revision 1.14
	distrib/sets/lists/debug/shl.mi: revision 1.306
	tests/libexec/ld.elf_so/Makefile: revision 1.15
	tests/libexec/ld.elf_so/helper_abuse_static/Makefile: revision 1.1
	distrib/sets/lists/debug/shl.mi: revision 1.307
	tests/libexec/ld.elf_so/Makefile: revision 1.16
	tests/libexec/ld.elf_so/helper_abuse_static/Makefile: revision 1.2
	distrib/sets/lists/debug/shl.mi: revision 1.308
	tests/libexec/ld.elf_so/Makefile: revision 1.17
	distrib/sets/lists/debug/shl.mi: revision 1.309
	tests/libexec/ld.elf_so/Makefile: revision 1.18
	tests/libexec/ld.elf_so/Makefile: revision 1.19
	libexec/ld.elf_so/tls.c: revision 1.16
	libexec/ld.elf_so/tls.c: revision 1.17
	libexec/ld.elf_so/tls.c: revision 1.18
	libexec/ld.elf_so/tls.c: revision 1.19
	tests/libexec/ld.elf_so/helper_onlydef_static/h_onlydef_static.c: revision 1.1
	tests/libexec/ld.elf_so/helper_use_static/h_use_static.c: revision 1.1
	tests/libexec/ld.elf_so/helper_use_static/h_use_static.c: revision 1.2
	tests/libexec/ld.elf_so/helper_def_static/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_def_static/Makefile: revision 1.2
	libexec/ld.elf_so/arch/hppa/hppa_reloc.c: revision 1.50
	distrib/sets/lists/debug/shl.mi: revision 1.310
	libexec/ld.elf_so/README.TLS: revision 1.6
	distrib/sets/lists/debug/shl.mi: revision 1.311
	distrib/sets/lists/debug/shl.mi: revision 1.314
	tests/libexec/ld.elf_so/helper_dso3/Makefile: revision 1.2
	tests/libexec/ld.elf_so/helper_symver_dso1/Makefile: revision 1.4
	libexec/ld.elf_so/arch/powerpc/ppc_reloc.c: revision 1.63
	tests/libexec/ld.elf_so/helper_def_dynamic/h_def_dynamic.c: revision 1.1
	tests/libexec/ld.elf_so/helper_onlydef/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_onlydef/Makefile: revision 1.2
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.10
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.11
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.12
	libexec/ld.elf_so/map_object.c: revision 1.66
	tests/libexec/ld.elf_so/helper.mk: revision 1.1
	libexec/ld.elf_so/arch/sparc/mdreloc.c: revision 1.57
	libexec/ld.elf_so/map_object.c: revision 1.67
	tests/libexec/ld.elf_so/helper_onlydef/h_onlydef.c: revision 1.1
	tests/libexec/ld.elf_so/helper_symver_dso2/Makefile: revision 1.4
	tests/libexec/ld.elf_so/helper_use_static/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_use_static/Makefile: revision 1.2
	tests/libexec/ld.elf_so/helper_use_static/Makefile: revision 1.3
	tests/libexec/ld.elf_so/helper_use_dynamic/h_use_dynamic.c: revision 1.1
	tests/libexec/ld.elf_so/helper_abuse_static/h_abuse_static.c: revision 1.1
	libexec/ld.elf_so/arch/riscv/mdreloc.c: revision 1.9
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.1
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.2
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.3
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.4
	tests/libexec/ld.elf_so/helper_onlyctor_dynamic/Makefile: revision 1.1
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.5
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.6
	libexec/ld.elf_so/arch/m68k/mdreloc.c: revision 1.34
	tests/libexec/ld.elf_so/helper_onlyctor_dynamic/Makefile: revision 1.2
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.7
	libexec/ld.elf_so/arch/i386/mdreloc.c: revision 1.42
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.8
	libexec/ld.elf_so/arch/i386/mdreloc.c: revision 1.43
	libexec/ld.elf_so/arch/or1k/mdreloc.c: revision 1.4
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.9
	tests/libexec/ld.elf_so/helper_onlyuse_dynamic/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_onlyuse_dynamic/Makefile: revision 1.2
	tests/libexec/ld.elf_so/helper_abuse_dynamic/h_abuse_dynamic.c: revision 1.1
	tests/libexec/ld.elf_so/helper_onlyctor_dynamic/h_onlyctor_dynamic.c: revision 1.1
	tests/libexec/ld.elf_so/helper_onlyuse_static/h_onlyuse_static.c: revision 1.1
	tests/libexec/ld.elf_so/helper_onlyuse_dynamic/h_onlyuse_dynamic.c: revision 1.1
	tests/libexec/ld.elf_so/helper_dso1/Makefile: revision 1.2
	distrib/sets/lists/tests/shl.mi: revision 1.12
	distrib/sets/lists/tests/shl.mi: revision 1.13
	libexec/ld.elf_so/arch/alpha/alpha_reloc.c: revision 1.44

ld.elf_so: New test for extern initial-exec TLS, PR toolchain/50277.

ld.elf_so: Fix extern TLS test to match PR toolchain/50277.
Now it's actually testing the problem.
ld.elf_so: Nix inadvertently committed private test program.
ld.elf_so: Fix set lists for MKDEBUG=yes builds with t_tls_extern.

ld.elf_so: Sprinkle tls debug messages.

ld.elf_so: Make tls alloc debug messages more detailed and greppable.

ld.elf_so: Test variations on PR toolchain/50277.

ld.elf_so: Test extern dynamic TLS too.

ld.elf_so: Factor out logic in TLS tests to make writing more easier.
No functional change intended.

ld.elf_so: Test TLS abuse of static def, dynamic use and vice versa.

ld.elf_so: Shorter test names.
No functional non-cosmetic change intended.

ld.elf_so: Separately test eager and lazy resolution of def tls ptr.
eager: before loading use library
lazy: after loading use library

Add recent ld.elf_so test helpers debug info
ld.elf_so: Add new files to debug/shl.mi.

ld.elf_so: tls_extern dynamic_defabuse_eager must xfail differently.
If a symbol has already been resolved as dynamic TLS, any library
that tries to use it as static TLS cannot be dlopened.

ld.elf_so: Test another edge case of mismatched TLS models.
One library defines a symbol and _doesn't_ use it, so it has no
indication of whether the symbol is for static TLS or dynamic TLS,
and then two other libraries use it in different ways.

ld.elf_so: Test dynamic-then-static abuse via ctor.

ld.elf_so: Fix missing tab in debug/shl.mi in last change.

Fix interactions of initial-exec TLS model and dlopen

(1) If an initial-exec relocation was used for a non-local symbol
(i.e. the definition of the symbol is in a different DSO), the
computation of the static TLS offset used the wrong DSO.

This would effectively mean the wrong address was computed
(PR toolchain/50277, PR pkg/57445).
Fix this by forcing the computation of the correct DSO (the one defining
the symbol).
This code uses __UNCONST to avoid the vast interface changes for this
special case.

(2) If symbols from a DSO loaded via dlopen are used with both
global-dynamic/local-dynamic and initial-exec relocations AND
a initial-exec relocation was resolved first in a thread, a split brain
situation could exist where the dynamic relocations would use one memory
block (separate allocation) and the initial-exec relocations the static
per-thread TLS space.

(3) If the initial-exec relocation in (2) is seen after any thread has
already used a GD/LD allocation, bail out. Since IE relocations are used
only in the GOT, this will prevent the dlopen. This is a bit more
aggressive than necessary, but a full blown reference counting doesn't
seem to be justified.
Avoid using uninitialized variable "symnum" when building with DEBUG
enabled by borrowing the rdbg_symname() macro from arch/x86_64.
ld.elf_so: Sprinkle more debug messages on dlopen and error.

PR pkg/57445

Fix MKDEBUGLIB build by adding these installed files to the debug
set list.

One could argue that these files are not of any use, so why install
them?  I don't have a good argument either way, and this is (for
now) a simple work-around for PR bin/57455   Please feel free to
commit a different fix to avoid installing these files at all.

Fix markup of libh_ MKDEBUGLIB=yes only files

TLS variant I archs need to fudge the offset by the size of the TCB.
tests/libexec/ld.elf_so: Fix helper library makefiles.
1. Consolidate logic into a single helper.mk to reduce duplication.
2. Set NO* variables, not MK* variables which are reserved for user.
3. Avoid eager X!= in favour of lazy ${X:sh}.
4. Mark _g.a set list entries obsolete.  Never should've been built!
PR misc/57462
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.70 2023/06/04 01:24:58 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.70 2023/06/04 01:24:58 joerg Exp $");
d386 3
a388 3
				if (!defobj->tls_static &&
				    _rtld_tls_offset_allocate(__UNCONST(defobj)))
					return -1;
@


1.69.12.1
log
@Pull up following revision(s) (requested by riastradh in ticket #297):

	distrib/sets/lists/tests/shl.mi: revision 1.14
	distrib/sets/lists/tests/shl.mi: revision 1.15
	distrib/sets/lists/tests/shl.mi: revision 1.16
	tests/libexec/ld.elf_so/helper_def_static/h_def_static.c: revision 1.1
	tests/libexec/ld.elf_so/helper_def_dynamic/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_def_dynamic/Makefile: revision 1.2
	tests/libexec/ld.elf_so/helper_onlyuse_static/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_onlyuse_static/Makefile: revision 1.2
	libexec/ld.elf_so/arch/mips/mips_reloc.c: revision 1.75
	distrib/sets/lists/tests/mi: revision 1.1265
	libexec/ld.elf_so/arch/sh3/mdreloc.c: revision 1.36
	libexec/ld.elf_so/rtld.c: revision 1.214
	tests/libexec/ld.elf_so/helper_onlydef_static/Makefile: revision 1.1
	distrib/sets/lists/debug/mi: revision 1.400
	tests/libexec/ld.elf_so/helper_onlydef_static/Makefile: revision 1.2
	distrib/sets/lists/debug/mi: revision 1.401
	distrib/sets/lists/debug/mi: revision 1.402
	tests/libexec/ld.elf_so/helper_dso2/Makefile: revision 1.2
	distrib/sets/lists/debug/mi: revision 1.403
	tests/libexec/ld.elf_so/helper_symver_dso0/Makefile: revision 1.2
	libexec/ld.elf_so/arch/x86_64/mdreloc.c: revision 1.48
	distrib/sets/lists/debug/mi: revision 1.406
	tests/libexec/ld.elf_so/helper_use_dynamic/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_use_dynamic/Makefile: revision 1.2
	tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile: revision 1.2
	libexec/ld.elf_so/arch/sparc64/mdreloc.c: revision 1.70
	libexec/ld.elf_so/arch/aarch64/mdreloc.c: revision 1.18
	tests/libexec/ld.elf_so/helper_abuse_dynamic/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_abuse_dynamic/Makefile: revision 1.2
	tests/libexec/ld.elf_so/Makefile: revision 1.13
	libexec/ld.elf_so/arch/arm/mdreloc.c: revision 1.46
	libexec/ld.elf_so/rtld.h: revision 1.146
	tests/libexec/ld.elf_so/Makefile: revision 1.14
	distrib/sets/lists/debug/shl.mi: revision 1.306
	tests/libexec/ld.elf_so/Makefile: revision 1.15
	tests/libexec/ld.elf_so/helper_abuse_static/Makefile: revision 1.1
	distrib/sets/lists/debug/shl.mi: revision 1.307
	tests/libexec/ld.elf_so/Makefile: revision 1.16
	tests/libexec/ld.elf_so/helper_abuse_static/Makefile: revision 1.2
	distrib/sets/lists/debug/shl.mi: revision 1.308
	tests/libexec/ld.elf_so/Makefile: revision 1.17
	distrib/sets/lists/debug/shl.mi: revision 1.309
	tests/libexec/ld.elf_so/Makefile: revision 1.18
	tests/libexec/ld.elf_so/Makefile: revision 1.19
	libexec/ld.elf_so/tls.c: revision 1.16
	libexec/ld.elf_so/tls.c: revision 1.17
	libexec/ld.elf_so/tls.c: revision 1.18
	libexec/ld.elf_so/tls.c: revision 1.19
	tests/libexec/ld.elf_so/helper_onlydef_static/h_onlydef_static.c: revision 1.1
	tests/libexec/ld.elf_so/helper_use_static/h_use_static.c: revision 1.1
	tests/libexec/ld.elf_so/helper_use_static/h_use_static.c: revision 1.2
	tests/libexec/ld.elf_so/helper_def_static/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_def_static/Makefile: revision 1.2
	libexec/ld.elf_so/arch/hppa/hppa_reloc.c: revision 1.50
	distrib/sets/lists/debug/shl.mi: revision 1.310
	libexec/ld.elf_so/README.TLS: revision 1.6
	distrib/sets/lists/debug/shl.mi: revision 1.311
	distrib/sets/lists/debug/shl.mi: revision 1.314
	tests/libexec/ld.elf_so/helper_dso3/Makefile: revision 1.2
	tests/libexec/ld.elf_so/helper_symver_dso1/Makefile: revision 1.4
	libexec/ld.elf_so/arch/powerpc/ppc_reloc.c: revision 1.63
	tests/libexec/ld.elf_so/helper_def_dynamic/h_def_dynamic.c: revision 1.1
	tests/libexec/ld.elf_so/helper_onlydef/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_onlydef/Makefile: revision 1.2
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.10
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.11
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.12
	libexec/ld.elf_so/map_object.c: revision 1.66
	tests/libexec/ld.elf_so/helper.mk: revision 1.1
	libexec/ld.elf_so/arch/sparc/mdreloc.c: revision 1.57
	libexec/ld.elf_so/map_object.c: revision 1.67
	tests/libexec/ld.elf_so/helper_onlydef/h_onlydef.c: revision 1.1
	tests/libexec/ld.elf_so/helper_symver_dso2/Makefile: revision 1.4
	tests/libexec/ld.elf_so/helper_use_static/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_use_static/Makefile: revision 1.2
	tests/libexec/ld.elf_so/helper_use_static/Makefile: revision 1.3
	tests/libexec/ld.elf_so/helper_use_dynamic/h_use_dynamic.c: revision 1.1
	tests/libexec/ld.elf_so/helper_abuse_static/h_abuse_static.c: revision 1.1
	libexec/ld.elf_so/arch/riscv/mdreloc.c: revision 1.9
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.1
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.2
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.3
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.4
	tests/libexec/ld.elf_so/helper_onlyctor_dynamic/Makefile: revision 1.1
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.5
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.6
	libexec/ld.elf_so/arch/m68k/mdreloc.c: revision 1.34
	tests/libexec/ld.elf_so/helper_onlyctor_dynamic/Makefile: revision 1.2
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.7
	libexec/ld.elf_so/arch/i386/mdreloc.c: revision 1.42
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.8
	libexec/ld.elf_so/arch/i386/mdreloc.c: revision 1.43
	libexec/ld.elf_so/arch/or1k/mdreloc.c: revision 1.4
	tests/libexec/ld.elf_so/t_tls_extern.c: revision 1.9
	tests/libexec/ld.elf_so/helper_onlyuse_dynamic/Makefile: revision 1.1
	tests/libexec/ld.elf_so/helper_onlyuse_dynamic/Makefile: revision 1.2
	tests/libexec/ld.elf_so/helper_abuse_dynamic/h_abuse_dynamic.c: revision 1.1
	tests/libexec/ld.elf_so/helper_onlyctor_dynamic/h_onlyctor_dynamic.c: revision 1.1
	tests/libexec/ld.elf_so/helper_onlyuse_static/h_onlyuse_static.c: revision 1.1
	tests/libexec/ld.elf_so/helper_onlyuse_dynamic/h_onlyuse_dynamic.c: revision 1.1
	tests/libexec/ld.elf_so/helper_dso1/Makefile: revision 1.2
	distrib/sets/lists/tests/shl.mi: revision 1.12
	distrib/sets/lists/tests/shl.mi: revision 1.13
	libexec/ld.elf_so/arch/alpha/alpha_reloc.c: revision 1.44
	(all via patch)

ld.elf_so: New test for extern initial-exec TLS, PR toolchain/50277.

ld.elf_so: Fix extern TLS test to match PR toolchain/50277.
Now it's actually testing the problem.
ld.elf_so: Nix inadvertently committed private test program.
ld.elf_so: Fix set lists for MKDEBUG=yes builds with t_tls_extern.

ld.elf_so: Sprinkle tls debug messages.

ld.elf_so: Make tls alloc debug messages more detailed and greppable.

ld.elf_so: Test variations on PR toolchain/50277.

ld.elf_so: Test extern dynamic TLS too.

ld.elf_so: Factor out logic in TLS tests to make writing more easier.
No functional change intended.

ld.elf_so: Test TLS abuse of static def, dynamic use and vice versa.

ld.elf_so: Shorter test names.
No functional non-cosmetic change intended.

ld.elf_so: Separately test eager and lazy resolution of def tls ptr.
eager: before loading use library
lazy: after loading use library

Add recent ld.elf_so test helpers debug info
ld.elf_so: Add new files to debug/shl.mi.

ld.elf_so: tls_extern dynamic_defabuse_eager must xfail differently.
If a symbol has already been resolved as dynamic TLS, any library
that tries to use it as static TLS cannot be dlopened.

ld.elf_so: Test another edge case of mismatched TLS models.
One library defines a symbol and _doesn't_ use it, so it has no
indication of whether the symbol is for static TLS or dynamic TLS,
and then two other libraries use it in different ways.

ld.elf_so: Test dynamic-then-static abuse via ctor.

ld.elf_so: Fix missing tab in debug/shl.mi in last change.

Fix interactions of initial-exec TLS model and dlopen
(1) If an initial-exec relocation was used for a non-local symbol
(i.e. the definition of the symbol is in a different DSO), the
computation of the static TLS offset used the wrong DSO.
This would effectively mean the wrong address was computed
(PR toolchain/50277, PR pkg/57445).
Fix this by forcing the computation of the correct DSO (the one defining
the symbol).
This code uses __UNCONST to avoid the vast interface changes for this
special case.
(2) If symbols from a DSO loaded via dlopen are used with both
global-dynamic/local-dynamic and initial-exec relocations AND
a initial-exec relocation was resolved first in a thread, a split brain
situation could exist where the dynamic relocations would use one memory
block (separate allocation) and the initial-exec relocations the static
per-thread TLS space.
(3) If the initial-exec relocation in (2) is seen after any thread has
already used a GD/LD allocation, bail out. Since IE relocations are used
only in the GOT, this will prevent the dlopen. This is a bit more
aggressive than necessary, but a full blown reference counting doesn't
seem to be justified.
Avoid using uninitialized variable "symnum" when building with DEBUG
enabled by borrowing the rdbg_symname() macro from arch/x86_64.
ld.elf_so: Sprinkle more debug messages on dlopen and error.
PR pkg/57445
Fix MKDEBUGLIB build by adding these installed files to the debug
set list.
XXX
One could argue that these files are not of any use, so why install
them?  I don't have a good argument either way, and this is (for
now) a simple work-around for PR bin/57455   Please feel free to
commit a different fix to avoid installing these files at all.
Fix markup of libh_ MKDEBUGLIB=yes only files
TLS variant I archs need to fudge the offset by the size of the TCB.
tests/libexec/ld.elf_so: Fix helper library makefiles.
1. Consolidate logic into a single helper.mk to reduce duplication.
2. Set NO* variables, not MK* variables which are reserved for user.
3. Avoid eager X!= in favour of lazy ${X:sh}.
4. Mark _g.a set list entries obsolete.  Never should've been built!
PR misc/57462
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.70 2023/06/04 01:24:58 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.70 2023/06/04 01:24:58 joerg Exp $");
d386 3
a388 3
				if (!defobj->tls_static &&
				    _rtld_tls_offset_allocate(__UNCONST(defobj)))
					return -1;
@


1.68
log
@Move the complex logic for dynamically writing branches from ld.elf_so
into a header for reuse in crt0.o for static ifunc support. Change the
existing logic for sparc64 to use the Bicc variant of ba,a as it allows
+-8MB displacement compared to the BPcc variant's +-1MB. Teach the sparc
variant the same trick for using ba,a and not sethi+jmp when possible.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.67 2017/12/25 17:00:15 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.67 2017/12/25 17:00:15 joerg Exp $");
d326 4
a329 2
			if (obj->ifunc_remaining_nonplt == 0)
				obj->ifunc_remaining_nonplt = rela - obj->rela + 1;
a637 34

void
_rtld_call_ifunc(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
{
	const Elf_Rela *rela;
	Elf_Addr *where;
	Elf_Word *where2;
	Elf_Addr target;

	while (obj->ifunc_remaining > 0 && _rtld_objgen == cur_objgen) {
		rela = obj->pltrelalim - --obj->ifunc_remaining;
		if (ELF_R_TYPE(rela->r_info) != R_TYPE(JMP_IREL))
			continue;
		where2 = (Elf_Word *)(obj->relocbase + rela->r_offset);
		target = (Elf_Addr)(obj->relocbase + rela->r_addend);
		_rtld_exclusive_exit(mask);
		target = _rtld_resolve_ifunc2(obj, target);
		_rtld_exclusive_enter(mask);
		sparc_write_branch(where2 + 1, (void *)target);
	}

	while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
		rela = obj->relalim - --obj->ifunc_remaining_nonplt;
		if (ELF_R_TYPE(rela->r_info) != R_TYPE(IRELATIVE))
			continue;
		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
		target = (Elf_Addr)(obj->relocbase + rela->r_addend);
		_rtld_exclusive_exit(mask);
		target = _rtld_resolve_ifunc2(obj, target);
		_rtld_exclusive_enter(mask);
		if (*where != target)
			*where = target;
	}
}
@


1.67
log
@Since GNU ld doesn't honor the PLT entry reservation, also compensate
for JMP_IREL relocations at the start of the PLT.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.66 2017/11/06 21:16:04 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.66 2017/11/06 21:16:04 joerg Exp $");
d38 2
a196 13
#define	BAA	0x30680000	/*	ba,a	%xcc, 0 */
#define	SETHI	0x03000000	/*	sethi	%hi(0), %g1 */
#define	JMP	0x81c06000	/*	jmpl	%g1+%lo(0), %g0 */
#define	NOP	0x01000000	/*	sethi	%hi(0), %g0 */
#define	OR	0x82106000	/*	or	%g1, 0, %g1 */
#define	XOR	0x82186000	/*	xor	%g1, 0, %g1 */
#define	MOV71	0x8213e000	/*	or	%o7, 0, %g1 */
#define	MOV17	0x9e106000	/*	or	%g1, 0, %o7 */
#define	CALL	0x40000000	/*	call	0 */
#define	SLLX	0x83287000	/*	sllx	%g1, 0, %g1 */
#define	NEG	0x82200001	/*	neg	%g1 */
#define	SETHIG5	0x0b000000	/*	sethi	%hi(0), %g5 */
#define	ORG5	0x82104005	/*	or	%g1, %g5, %g1 */
a580 28
	Elf_Addr offset, offBAA;

	/*
	 * At the PLT entry pointed at by `where', we now construct a direct
	 * transfer to the now fully resolved function address.
	 *
	 * A PLT entry is supposed to start by looking like this:
	 *
	 *	sethi	%hi(. - .PLT0), %g1
	 *	ba,a	%xcc, .PLT1
	 *	nop
	 *	nop
	 *	nop
	 *	nop
	 *	nop
	 *	nop
	 *
	 * When we replace these entries we start from the last instruction
	 * and do it in reverse order so the last thing we do is replace the
	 * branch.  That allows us to change this atomically.
	 *
	 * We now need to find out how far we need to jump.  We have a choice
	 * of several different relocation techniques which are increasingly
	 * expensive.
	 */

	offset = ((Elf_Addr)where) - value;
	offBAA = value - (((Elf_Addr)where) + 4);	/* ba,a at where[1] */
a588 135
	} else if (offBAA <= (1L<<20) && (Elf_SOff)offBAA >= -(1L<<20)) {
		/* 
		 * We're within 1MB -- we can use a direct branch insn.
		 *
		 * We can generate this pattern:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	ba,a	%xcc, addr
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[1] = BAA | ((offBAA >> 2) & 0x7ffff);
		__asm volatile("iflush %0+4" : : "r" (where));
	} else if (value < (1L<<32)) {
		/* 
		 * We're within 32-bits of address zero.
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%hi(addr), %g1
		 *	jmp	%g1+%lo(addr)
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[2] = JMP   | LOVAL(value, 0);
		where[1] = SETHI | HIVAL(value, 10);
		__asm volatile("iflush %0+8" : : "r" (where));
		__asm volatile("iflush %0+4" : : "r" (where));
	} else if ((Elf_SOff)value <= 0 && (Elf_SOff)value > -(1L<<32)) {
		/* 
		 * We're within 32-bits of address -1.
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%hix(addr), %g1
		 *	xor	%g1, %lox(addr), %g1
		 *	jmp	%g1
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[3] = JMP;
		where[2] = XOR | (value & 0x00003ff) | 0x1c00;
		where[1] = SETHI | HIVAL(~value, 10);
		__asm volatile("iflush %0+12" : : "r" (where));
		__asm volatile("iflush %0+8" : : "r" (where));
		__asm volatile("iflush %0+4" : : "r" (where));
	} else if ((offset+8) <= (1L<<31) &&
	    (Elf_SOff)(offset+8) >= -((1L<<31) - 4)) {
		/* 
		 * We're within 32-bits -- we can use a direct call insn 
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	mov	%o7, %g1
		 *	call	(.+offset)
		 *	 mov	%g1, %o7
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		offset += 8;	/* call is at where[2], 8 byte further */
		where[3] = MOV17;
		where[2] = CALL	  | ((-offset >> 2) & 0x3fffffff);
		where[1] = MOV71;
		__asm volatile("iflush %0+12" : : "r" (where));
		__asm volatile("iflush %0+8" : : "r" (where));
		__asm volatile("iflush %0+4" : : "r" (where));
	} else if ((Elf_SOff)value > 0 && value < (1L<<44)) {
		/* 
		 * We're within 44 bits.  We can generate this pattern:
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%h44(addr), %g1
		 *	or	%g1, %m44(addr), %g1
		 *	sllx	%g1, 12, %g1	
		 *	jmp	%g1+%l44(addr)	
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[4] = JMP   | LOVAL(value, 0);
		where[3] = SLLX  | 12;
		where[2] = OR    | (((value) >> 12) & 0x00001fff);
		where[1] = SETHI | HIVAL(value, 22);
		__asm volatile("iflush %0+16" : : "r" (where));
		__asm volatile("iflush %0+12" : : "r" (where));
		__asm volatile("iflush %0+8" : : "r" (where));
		__asm volatile("iflush %0+4" : : "r" (where));
	} else if ((Elf_SOff)value < 0 && (Elf_SOff)value > -(1L<<44)) {
		/*
		 *  We're within 44 bits.  We can generate this pattern:
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%hi((-addr)>>12), %g1
		 *	or	%g1, %lo((-addr)>>12), %g1
		 *	neg	%g1
		 *	sllx	%g1, 12, %g1
		 *	jmp	%g1+(addr&0x0fff)
		 *	nop
		 *	nop
		 *
		 */
		Elf_Addr neg = (~value+1)>>12;
		where[5] = JMP   | (value & 0x0fff);
		where[4] = SLLX  | 12;
		where[3] = NEG;
		where[2] = OR    | (LOVAL(neg, 0)+1);
		where[1] = SETHI | HIVAL(neg, 10);
		__asm volatile("iflush %0+20" : : "r" (where));
		__asm volatile("iflush %0+16" : : "r" (where));
		__asm volatile("iflush %0+12" : : "r" (where));
		__asm volatile("iflush %0+8" : : "r" (where));
		__asm volatile("iflush %0+4" : : "r" (where));
d590 1
a590 27
		/* 
		 * We need to load all 64-bits
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%hh(addr), %g1
		 *	sethi	%lm(addr), %g5
		 *	or	%g1, %hm(addr), %g1
		 *	sllx	%g1, 32, %g1
		 *	or	%g1, %g5, %g1
		 *	jmp	%g1+%lo(addr)
		 *	nop
		 *
		 */
		where[6] = JMP     | LOVAL(value, 0);
		where[5] = ORG5;
		where[4] = SLLX    | 32;
		where[3] = OR      | LOVAL(value, 32);
		where[2] = SETHIG5 | HIVAL(value, 10);
		where[1] = SETHI   | HIVAL(value, 42);
		__asm volatile("iflush %0+24" : : "r" (where));
		__asm volatile("iflush %0+20" : : "r" (where));
		__asm volatile("iflush %0+16" : : "r" (where));
		__asm volatile("iflush %0+12" : : "r" (where));
		__asm volatile("iflush %0+8" : : "r" (where));
		__asm volatile("iflush %0+4" : : "r" (where));
d654 1
a654 1
		_rtld_write_plt(where2, target, NULL, obj);
@


1.67.2.1
log
@Resolve conflicts between branch and HEAD
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.68 2018/03/29 13:23:39 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.68 2018/03/29 13:23:39 joerg Exp $");
a37 2
#include <machine/elf_support.h>

d195 13
d592 28
d628 135
d764 27
a790 1
		sparc_write_branch(where + 1, (void *)value);
d854 1
a854 1
		sparc_write_branch(where2 + 1, (void *)target);
@


1.67.2.2
log
@Sync with HEAD.  77 conflicts resolved - all of them $NetBSD$
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.69 2018/04/03 21:10:27 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.69 2018/04/03 21:10:27 joerg Exp $");
d326 2
a327 4
			if (obj->ifunc_remaining_nonplt == 0) {
				obj->ifunc_remaining_nonplt =
				    obj->relalim - rela;
			}
d636 34
@


1.66
log
@init/fini for the main program is handled by crt0.o, so ifunc handling
is skipped right now as it iterates the same list. Don't repeat that
mistake and explicitly take care of it in the dynamic linker.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.65 2017/08/12 09:03:27 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.65 2017/08/12 09:03:27 joerg Exp $");
d536 2
a537 1
	if (ELF_R_TYPE(obj->pltrela->r_info) == R_TYPE(JMP_SLOT)) {
d550 3
a552 2
		 * JMP_SLOT.  If it is JMP_SLOT, then the 4 reserved entries
		 * were not generated and our index is 4 entries too far.
d577 2
a578 1
	if (ELF_R_TYPE(obj->pltrela->r_info) != R_TYPE(JMP_SLOT))
@


1.65
log
@Add sparc/sparc64 support for irelative relocations.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.64 2017/08/10 19:03:26 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.64 2017/08/10 19:03:26 joerg Exp $");
a518 3
	if (!obj->relocbase)
		return 0;

@


1.64
log
@Add IRELATIVE support for ARM, X86 and PowerPC.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.63 2017/07/24 08:08:34 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.63 2017/07/24 08:08:34 martin Exp $");
d335 7
d517 11
a527 1
	return (0);
d588 3
a590 7
/*
 * New inline function that is called by _rtld_relocate_plt_object and
 * _rtld_bind
 */
static inline int
_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
    Elf_Addr *tp)
d592 1
a592 23
	Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
	const Elf_Sym *def;
	const Obj_Entry *defobj;
	Elf_Addr value, offset, offBAA;
	unsigned long info = rela->r_info;

	assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));

	def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
	if (__predict_false(def == NULL))
		return -1;
	if (__predict_false(def == &_rtld_sym_zero))
		return 0;

	if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
		if (tp == NULL)
			return 0;
		value = _rtld_resolve_ifunc(defobj, def);
	} else {
		value = (Elf_Addr)(defobj->relocbase + def->st_value);
	}
	rdbg(("bind now/fixup in %s at %p --> new=%p", 
	    defobj->strtab + def->st_name, (void*)where, (void *)value));
d619 2
a620 2
	offBAA = value - (((Elf_Addr)where) +4);	/* ba,a at where[1] */
	if (rela->r_addend) {
a627 1

a665 1

a687 1

a711 1

a735 1

a762 1

d791 27
d819 6
d826 4
d836 34
@


1.63
log
@Fix thinko in previous: even if the address is an unsigned value and we
have verified the range before, we still need to mask the bit pattern
to the target instruction field.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.62 2017/07/23 14:37:51 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.62 2017/07/23 14:37:51 martin Exp $");
d508 1
a508 1
_rtld_relocate_plt_lazy(const Obj_Entry *obj)
@


1.62
log
@Simplify and fix the offset calculation when doing a %pc relative
branch from the PLT slot to the target.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.61 2017/06/19 11:57:02 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.61 2017/06/19 11:57:02 joerg Exp $");
d654 1
a654 1
		where[1] = BAA | (offBAA >> 2);
@


1.61
log
@Replace COMBREL with just-in-time check in _rtld_relocate_nonplt_objects.

The COMBREL logic predates thread-safety of the dynamic linker and
breaks the use of shared locks for the common symbol lookup case. It is
unlikely to provide any benefit for lazy binding or PLT lookups, so
provide equivalent functionality in the non-PLT relocation handling loop
by checking if the symbol used by the current relocation is the same as
the one used during the last lookup. No inter-object cachine is done as
it is also unlikely to be benefical.

Testing with Firefox startup on AMD64 shows a small performance gain by
the new method.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.60 2017/06/15 23:10:12 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.60 2017/06/15 23:10:12 joerg Exp $");
d582 1
a582 1
	Elf_Addr value, offset;
d628 1
d638 1
a638 1
	} else if (offset <= (1L<<20) && (Elf_SOff)offset >= -(1L<<20)) {
d654 1
a654 1
		where[1] = BAA | ((offset >> 2) & 0x7ffff);
@


1.60
log
@Fix indentation.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.59 2016/08/29 16:00:10 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.59 2016/08/29 16:00:10 martin Exp $");
d313 1
d319 1
a319 1
		unsigned long	 symnum;
a321 1
		symnum = ELF_R_SYM(rela->r_info);
d350 11
a366 5
				def = _rtld_find_symdef(symnum, obj,
				    &defobj, false);
				if (def == NULL)
					return -1;

a376 5
				def = _rtld_find_symdef(symnum, obj,
				    &defobj, false);
				if (def == NULL)
					return -1;

a387 5
				def = _rtld_find_symdef(symnum, obj,
				    &defobj, false);
				if (def == NULL)
					return -1;

a414 7

			/* Find the symbol */
			def = _rtld_find_symdef(symnum, obj, &defobj,
			    false);
			if (def == NULL)
				return -1;

@


1.59
log
@Despite the 10 in the name, the OLO10 relocation targets a 13 bit field,
the offset (O) providing the additional data.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.58 2016/06/20 08:12:25 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.58 2016/06/20 08:12:25 martin Exp $");
d355 47
a401 49
				case R_TYPE(TLS_DTPMOD64):
					def = _rtld_find_symdef(symnum, obj,
					    &defobj, false);
					if (def == NULL)
						return -1;

					*where = (Elf64_Addr)defobj->tlsindex;

					rdbg(("TLS_DTPMOD64 %s in %s --> %p",
					    obj->strtab +
					    obj->symtab[symnum].st_name,
					    obj->path, (void *)*where));

					break;

				case R_TYPE(TLS_DTPOFF64):
					def = _rtld_find_symdef(symnum, obj,
					    &defobj, false);
					if (def == NULL)
						return -1;

					*where = (Elf64_Addr)(def->st_value
					    + rela->r_addend);

					rdbg(("DTPOFF64 %s in %s --> %p",
					    obj->strtab +
					        obj->symtab[symnum].st_name,
					    obj->path, (void *)*where));

					break;

				case R_TYPE(TLS_TPOFF64):
					def = _rtld_find_symdef(symnum, obj,
					    &defobj, false);
					if (def == NULL)
						return -1;

					if (!defobj->tls_done &&
						_rtld_tls_offset_allocate(obj))
						     return -1;

					*where = (Elf64_Addr)(def->st_value -
			                            defobj->tlsoffset +
						    rela->r_addend);

		                        rdbg(("TLS_TPOFF64 %s in %s --> %p",
		                            obj->strtab +
					    obj->symtab[symnum].st_name,
		                            obj->path, (void *)*where));
d403 1
a403 1
	                		break;
@


1.59.6.1
log
@Pull up following revision(s) (requested by joerg in ticket #64):
	libexec/ld.elf_so/arch/arm/mdreloc.c: revision 1.40
	libexec/ld.elf_so/arch/arm/mdreloc.c: revision 1.41
	libexec/ld.elf_so/arch/hppa/hppa_reloc.c: revision 1.44
	libexec/ld.elf_so/arch/riscv/mdreloc.c: revision 1.3
	libexec/ld.elf_so/arch/aarch64/mdreloc.c: revision 1.3
	libexec/ld.elf_so/arch/sparc64/mdreloc.c: revision 1.60
	libexec/ld.elf_so/arch/m68k/mdreloc.c: revision 1.32
	libexec/ld.elf_so/arch/sparc64/mdreloc.c: revision 1.61
	libexec/ld.elf_so/arch/or1k/mdreloc.c: revision 1.2
	libexec/ld.elf_so/arch/sparc/mdreloc.c: revision 1.50
	libexec/ld.elf_so/arch/sh3/mdreloc.c: revision 1.33
	libexec/ld.elf_so/arch/sh3/mdreloc.c: revision 1.34
	libexec/ld.elf_so/arch/arm/mdreloc.c: revision 1.39
	libexec/ld.elf_so/symbol.c: revision 1.68
	libexec/ld.elf_so/arch/mips/mips_reloc.c: revision 1.66
	libexec/ld.elf_so/arch/mips/mips_reloc.c: revision 1.67
	libexec/ld.elf_so/arch/mips/mips_reloc.c: revision 1.68
	libexec/ld.elf_so/arch/x86_64/mdreloc.c: revision 1.42
	libexec/ld.elf_so/arch/powerpc/ppc_reloc.c: revision 1.54
	libexec/ld.elf_so/Makefile: revision 1.137
	libexec/ld.elf_so/arch/vax/mdreloc.c: revision 1.32
	libexec/ld.elf_so/rtld.h: revision 1.127
	libexec/ld.elf_so/arch/vax/mdreloc.c: revision 1.33
	libexec/ld.elf_so/arch/i386/mdreloc.c: revision 1.38
	libexec/ld.elf_so/arch/alpha/alpha_reloc.c: revision 1.42
	libexec/ld.elf_so/map_object.c: revision 1.58
	libexec/ld.elf_so/arch/sparc/mdreloc.c: revision 1.49
Replace COMBREL with just-in-time check in _rtld_relocate_nonplt_objects.
The COMBREL logic predates thread-safety of the dynamic linker and
breaks the use of shared locks for the common symbol lookup case. It is
unlikely to provide any benefit for lazy binding or PLT lookups, so
provide equivalent functionality in the non-PLT relocation handling loop
by checking if the symbol used by the current relocation is the same as
the one used during the last lookup. No inter-object cachine is done as
it is also unlikely to be benefical.
Testing with Firefox startup on AMD64 shows a small performance gain by
the new method.
Drop symbol number from default branch diagnostic, it isn't set at this
point and most likely not valid either.
Expand symnum, GCC's uninitialized used tracking is too imprecise.
Fix C&P bug. Deal with more MIPS hacks overriding def.
Add last_symnum, move up def and defobj.
Add back symnum, fix debug print.
Replace last use of r_type.
Fix indentation.
Fix indentation.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.59 2016/08/29 16:00:10 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.59 2016/08/29 16:00:10 martin Exp $");
a312 1
	unsigned long last_symnum = ULONG_MAX;
d318 1
a318 1
		unsigned long symnum;
d321 1
a349 11
		if (RELOC_RESOLVE_SYMBOL(type) || RELOC_TLS(type)) {
			symnum = ELF_R_SYM(rela->r_info);
			if (last_symnum != symnum) {
				last_symnum = symnum;
				def = _rtld_find_symdef(symnum, obj, &defobj,
				    false);
				if (def == NULL)
					return -1;
			}
		}

d355 49
a403 18
			case R_TYPE(TLS_DTPMOD64):
				*where = (Elf64_Addr)defobj->tlsindex;

				rdbg(("TLS_DTPMOD64 %s in %s --> %p",
				    obj->strtab +
				    obj->symtab[symnum].st_name,
				    obj->path, (void *)*where));

				break;

			case R_TYPE(TLS_DTPOFF64):
				*where = (Elf64_Addr)(def->st_value
				    + rela->r_addend);

				rdbg(("DTPOFF64 %s in %s --> %p",
				    obj->strtab +
				        obj->symtab[symnum].st_name,
				    obj->path, (void *)*where));
d405 1
a405 15
				break;

			case R_TYPE(TLS_TPOFF64):
				if (!defobj->tls_done &&
					_rtld_tls_offset_allocate(obj))
					     return -1;

				*where = (Elf64_Addr)(def->st_value -
				    defobj->tlsoffset + rela->r_addend);

				rdbg(("TLS_TPOFF64 %s in %s --> %p",
				    obj->strtab + obj->symtab[symnum].st_name,
				    obj->path, (void *)*where));

				break;
d421 7
@


1.59.6.2
log
@Pull up following revision(s) (requested by martin in ticket #156):
	libexec/ld.elf_so/arch/sparc64/mdreloc.c: 1.62, 1.63
Simplify and fix the offset calculation when doing a %pc relative
branch from the PLT slot to the target.
--
Fix thinko in previous: even if the address is an unsigned value and we
have verified the range before, we still need to mask the bit pattern
to the target instruction field.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.59.6.1 2017/07/04 12:47:58 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.59.6.1 2017/07/04 12:47:58 martin Exp $");
d582 1
a582 1
	Elf_Addr value, offset, offBAA;
a627 1
	offBAA = value - (((Elf_Addr)where) +4);	/* ba,a at where[1] */
d637 1
a637 1
	} else if (offBAA <= (1L<<20) && (Elf_SOff)offBAA >= -(1L<<20)) {
d653 1
a653 1
		where[1] = BAA | ((offBAA >> 2) & 0x7ffff);
@


1.58
log
@Fix a few bounds and instruction sequences generated in the PLT; exercised
by ASLR and verified to work with the aslr fixed random debug sysctls.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.57 2014/08/25 20:40:53 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.57 2014/08/25 20:40:53 joerg Exp $");
d178 1
a178 1
	_BM(10), _BM(22),		/* _OLO10, _HH22 */
@


1.57
log
@Add basic support for indirect functions. It allows providing a public
function symbol with an implementation choosen at run time.
Refactor calls to functions by address in ld.elf_so to create temporary
function descriptors on the stack, if the address is not leaked outside.

Limitations:
- no support for initialising static storage with function pointers
- no support for unnamed resolver functions

Inspired by FreeBSD's r228435 by kib@@freebsd.org.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.56 2014/04/02 14:11:25 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.56 2014/04/02 14:11:25 martin Exp $");
d205 1
d666 1
a666 1
		where[1] = BAA | ((offset >> 2) & 0x3fffff);
d712 2
a713 1
	} else if (offset <= (1L<<32) && (Elf_SOff)offset >= -((1L<<32) - 4)) {
d729 1
d731 1
a731 1
		where[2] = CALL	  | ((offset >> 4) & 0x3fffffff);
d737 1
a737 1
	} else if (offset < (1L<<44)) {
d753 1
a753 1
		where[4] = JMP   | LOVAL(offset, 0);
d755 2
a756 2
		where[2] = OR    | (((offset) >> 12) & 0x00001fff);
		where[1] = SETHI | HIVAL(offset, 22);
d762 3
a764 3
	} else if ((Elf_SOff)offset < 0 && (Elf_SOff)offset > -(1L<<44)) {
		/* 
		 * We're within 44 bits.  We can generate this pattern:
d769 5
a773 5
		 *	sethi	%h44(-addr), %g1
		 *	xor	%g1, %m44(-addr), %g1
		 *	sllx	%g1, 12, %g1	
		 *	jmp	%g1+%l44(addr)	
		 *	nop
d778 7
a784 4
		where[4] = JMP   | LOVAL(offset, 0);
		where[3] = SLLX  | 12;
		where[2] = XOR   | (((~offset) >> 12) & 0x00001fff);
		where[1] = SETHI | HIVAL(~offset, 22);
@


1.56
log
@The table of masks applied for each relocation type was wrong for some
relocs with 64bit targets, like GLOB_DAT.
Change some instruction patterns used for PLT slots, so -current
objdump -d shows what the comment says.
Fix encoding of %lox() in PLT slots "close" to -1.
Enhance debug output slightly.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.55 2013/10/03 10:45:57 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.55 2013/10/03 10:45:57 martin Exp $");
d605 7
a611 1
	value = (Elf_Addr)(defobj->relocbase + def->st_value);
@


1.56.4.1
log
@Catch up to -current, via patch, requested by christos in ticket #1126:
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.56 2014/04/02 14:11:25 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.56 2014/04/02 14:11:25 martin Exp $");
d605 1
a605 7
	if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
		if (tp == NULL)
			return 0;
		value = _rtld_resolve_ifunc(defobj, def);
	} else {
		value = (Elf_Addr)(defobj->relocbase + def->st_value);
	}
@


1.55
log
@The R_SPARC_L44 relocation type is documented to be truncating and
calculated as "(S + A) & 0xfff" - so while it (usually) sets a "imm13" field
in the opcode, only 12 bits of the calculated value can be used.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.54 2013/09/23 21:00:35 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.54 2013/09/23 21:00:35 martin Exp $");
d173 1
a173 1
	_BM(32), _BM(32), _BM(32),	/* _GLOB_DAT, JMP_SLOT, _RELATIVE */
d195 1
a195 1
#define	BAA	0x10400000	/*	ba,a	%xcc, 0 */
d199 4
a202 4
#define	OR	0x82806000	/*	or	%g1, 0, %g1 */
#define	XOR	0x82c06000	/*	xor	%g1, 0, %g1 */
#define	MOV71	0x8283a000	/*	or	%o7, 0, %g1 */
#define	MOV17	0x9c806000	/*	or	%g1, 0, %o7 */
d204 1
a204 1
#define	SLLX	0x8b407000	/*	sllx	%g1, 0, %g1 */
d206 1
a206 1
#define	ORG5	0x82804005	/*	or	%g1, %g5, %g1 */
d606 2
a607 2
	rdbg(("bind now/fixup in %s --> new=%p", 
	    defobj->strtab + def->st_name, (void *)value));
d699 1
a699 1
		where[2] = XOR | ((~value) & 0x00001fff);
@


1.54
log
@Missing , in table initializer
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.53 2012/07/22 09:21:03 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.53 2012/07/22 09:21:03 martin Exp $");
d186 1
a186 1
	_BM(22), _BM(10), _BM(13),	/* H44, M44, L44 */
@


1.53
log
@Add special handling needed for OLO10 relocations.
First part of fixing PR port-sparc64/46724.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.52 2011/03/30 08:37:52 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.52 2011/03/30 08:37:52 martin Exp $");
d183 1
a183 1
	_BM(7), _BM(5), _BM(6)		/* _7, _5, _6 */
@


1.53.2.1
log
@Rebase to HEAD as of a few days ago.
@
text
@d1 1
a1 1
/*	$NetBSD$	*/
d35 1
a35 1
__RCSID("$NetBSD$");
d173 1
a173 1
	-1, _BM(32), -1,		/* _GLOB_DAT, JMP_SLOT, _RELATIVE */
d183 1
a183 1
	_BM(7), _BM(5), _BM(6),		/* _7, _5, _6 */
d186 1
a186 1
	_BM(22), _BM(10), _BM(12),	/* H44, M44, L44 */
d195 1
a195 1
#define	BAA	0x30680000	/*	ba,a	%xcc, 0 */
d199 4
a202 4
#define	OR	0x82106000	/*	or	%g1, 0, %g1 */
#define	XOR	0x82186000	/*	xor	%g1, 0, %g1 */
#define	MOV71	0x8213e000	/*	or	%o7, 0, %g1 */
#define	MOV17	0x9e106000	/*	or	%g1, 0, %o7 */
d204 1
a204 1
#define	SLLX	0x83287000	/*	sllx	%g1, 0, %g1 */
d206 1
a206 1
#define	ORG5	0x82104005	/*	or	%g1, %g5, %g1 */
d606 2
a607 2
	rdbg(("bind now/fixup in %s at %p --> new=%p", 
	    defobj->strtab + def->st_name, (void*)where, (void *)value));
d699 1
a699 1
		where[2] = XOR | (value & 0x00003ff) | 0x1c00;
@


1.52
log
@Add support for 64 bit TLS relocations.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.51 2011/03/25 18:07:06 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.51 2011/03/25 18:07:06 joerg Exp $");
d326 4
d342 4
a345 2
		if (type > R_TYPE(TLS_TPOFF64))
			return (-1);
d431 5
@


1.52.4.1
log
@sync with head
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.52 2011/03/30 08:37:52 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.52 2011/03/30 08:37:52 martin Exp $");
a325 4
		/* OLO10 relocations have extra info */
		if ((type & 0x00ff) == R_SPARC_OLO10)
			type = R_SPARC_OLO10;

d338 2
a339 4
		if (type > R_TYPE(TLS_TPOFF64)) {
			dbg(("unknown relocation type %x at %p", type, rela));
			return -1;
		}
a424 5
		if (type == R_SPARC_OLO10) {
			value = (value & 0x3ff)
			    + (((Elf64_Xword)rela->r_info<<32)>>40);
		}

@


1.52.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.52.4.1 2012/10/30 18:59:23 yamt Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.52.4.1 2012/10/30 18:59:23 yamt Exp $");
d173 1
a173 1
	-1, _BM(32), -1,		/* _GLOB_DAT, JMP_SLOT, _RELATIVE */
d183 1
a183 1
	_BM(7), _BM(5), _BM(6),		/* _7, _5, _6 */
d186 1
a186 1
	_BM(22), _BM(10), _BM(12),	/* H44, M44, L44 */
d195 1
a195 1
#define	BAA	0x30680000	/*	ba,a	%xcc, 0 */
d199 4
a202 4
#define	OR	0x82106000	/*	or	%g1, 0, %g1 */
#define	XOR	0x82186000	/*	xor	%g1, 0, %g1 */
#define	MOV71	0x8213e000	/*	or	%o7, 0, %g1 */
#define	MOV17	0x9e106000	/*	or	%g1, 0, %o7 */
d204 1
a204 1
#define	SLLX	0x83287000	/*	sllx	%g1, 0, %g1 */
d206 1
a206 1
#define	ORG5	0x82104005	/*	or	%g1, %g5, %g1 */
d606 2
a607 2
	rdbg(("bind now/fixup in %s at %p --> new=%p", 
	    defobj->strtab + def->st_name, (void*)where, (void *)value));
d699 1
a699 1
		where[2] = XOR | (value & 0x00003ff) | 0x1c00;
@


1.52.6.1
log
@Pull up revisions:
  src/libexec/ld.elf_so/headers.c revision 1.42
  src/libexec/ld.elf_so/arch/sparc64/mdreloc.c revision 1.53
(requested by martin in ticket #447).

Remove a debug assert that does not hold for PIE (e.g. phdr = 0x40, but
obj has not been mapped at 0, so obj->phdr is 0x100040).
OK: skrll

Add special handling needed for OLO10 relocations.
First part of fixing PR port-sparc64/46724.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.52 2011/03/30 08:37:52 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.52 2011/03/30 08:37:52 martin Exp $");
a325 4
		/* OLO10 relocations have extra info */
		if ((type & 0x00ff) == R_SPARC_OLO10)
			type = R_SPARC_OLO10;

d338 2
a339 4
		if (type > R_TYPE(TLS_TPOFF64)) {
			dbg(("unknown relocation type %x at %p", type, rela));
			return -1;
		}
a424 5
		if (type == R_SPARC_OLO10) {
			value = (value & 0x3ff)
			    + (((Elf64_Xword)rela->r_info<<32)>>40);
		}

@


1.51
log
@Add basic locking to ld.elf_so.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.50 2010/09/24 12:00:10 skrll Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.50 2010/09/24 12:00:10 skrll Exp $");
d70 1
a70 1
static const int reloc_target_flags[] = {
d128 1
d143 7
a149 1
	"L44", "REGISTER", "UA64", "UA16"
d160 1
d336 1
a336 1
		 * Note: R_SPARC_UA16 is currently numerically largest.
d338 1
a338 1
		if (type > R_TYPE(UA16))
d344 60
@


1.50
log
@Comment reformat.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.49 2010/09/24 11:59:28 skrll Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.49 2010/09/24 11:59:28 skrll Exp $");
d474 1
d478 1
@


1.49
log
@Wrap long line.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.48 2010/09/24 11:57:11 skrll Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.48 2010/09/24 11:57:11 skrll Exp $");
d529 2
a530 3
	 * At the PLT entry pointed at by `where', we now construct
	 * a direct transfer to the now fully resolved function
	 * address.
d543 3
a545 4
	 * When we replace these entries we start from the second
	 * entry and do it in reverse order so the last thing we
	 * do is replace the branch.  That allows us to change this
	 * atomically.
d547 3
a549 3
	 * We now need to find out how far we need to jump.  We
	 * have a choice of several different relocation techniques
	 * which are increasingly expensive.
@


1.48
log
@Whitespace.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.47 2010/08/06 16:33:18 joerg Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.47 2010/08/06 16:33:18 joerg Exp $");
d507 2
a508 1
_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp)
@


1.47
log
@Reduce header pollution for mdreloc.c. Make Obj_Entry argument of
_rtld_relocate_nonplt_objects non-const in preparation for TLS support.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.46 2010/01/13 20:17:22 christos Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.46 2010/01/13 20:17:22 christos Exp $");
d557 1
a557 1
		 * This entry is >=32768.  The relocations points to a
d579 1
a579 1
		where[1] = BAA | ((offset >> 2) &0x3fffff);
@


1.46
log
@PR/39240: Satoshi Suetake: Don't fail when attempting to resolve weak symbols
when we are doing immediate binding, leave them alone and they will be dealt
with later during lazy binding. From skrll@@
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.45 2009/05/22 21:47:46 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.45 2009/05/22 21:47:46 martin Exp $");
a42 1
#include <sys/stat.h>
d299 1
a299 1
_rtld_relocate_nonplt_objects(const Obj_Entry *obj)
@


1.45
log
@Use the new Elf_SOff (signed offset) type to fix a few signed/unsigned
problems.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.44 2009/03/16 02:46:48 lukem Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.44 2009/03/16 02:46:48 lukem Exp $");
d476 1
a476 1
	if (err || result == 0)
d514 1
d516 1
a516 1
	/* Fully resolve procedure addresses now */
d518 2
a519 4
	assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));

	def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true);
	if (def == NULL)
d521 2
@


1.44
log
@Fix const issues (cast const pointers to "const uint8_t *" instead of "caddr_t")

NOTE: change based on ../i386/mdreloc.c 1.27
XXX: not compile tested
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.43 2008/07/24 04:39:25 matt Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.43 2008/07/24 04:39:25 matt Exp $");
d563 1
a563 1
	} else if (offset <= (1L<<20) && offset >= -(1L<<20)) {
d581 1
a581 1
	} else if (value >= 0 && value < (1L<<32)) {
d602 1
a602 1
	} else if (value <= 0 && value > -(1L<<32)) {
d625 1
a625 1
	} else if (offset <= (1L<<32) && offset >= -((1L<<32) - 4)) {
d648 1
a648 1
	} else if (offset >= 0 && offset < (1L<<44)) {
d673 1
a673 1
	} else if (offset < 0 && offset > -(1L<<44)) {
@


1.43
log
@Refactor common code to _rtld_relocate_plt_object to i386 and arm so they
act like the other versions.
In _rtld_bind, if the result is 0, call _rtld_die.
Initialize _rtld_sym_zero.st_value to -_rtld_objself.maprelocbase.  Now when
the symbol is resolved, st_value + maprelocbase will equal 0 and the above
check in _rtld_bind will fire and a call to NULL will be avoided.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.42 2008/04/28 20:23:04 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.42 2008/04/28 20:23:04 martin Exp $");
d292 1
a292 1
	relalim = (const Elf_Rela *)((caddr_t)rela + relasz);
@


1.43.4.1
log
@Pull up following revision(s) via patch (requested by skrll in ticket #1724):
	rescue/list.ldd: revision 1.4
	lib/libc/dlfcn/dlfcn_elf.c: revision 1.7
	libexec/ld.elf_so/arch/mips/mips_reloc.c: revision 1.57
	distrib/sets/lists/comp/mi: revision 1.1512
	share/man/man3/Makefile: revision 1.56
	libexec/ld.elf_so/arch/mips/mips_reloc.c: revision 1.58
	usr.bin/ldd/ldd.c: revision 1.15
	libexec/ld.elf_so/rtld.h: revision 1.84
	share/man/man3/dl_iterate_phdr.3: revision 1.1
	libexec/ld.elf_so/rtld.c: revision 1.129
	libexec/ld.elf_so/arch/powerpc/ppc_reloc.c: revision 1.44
	libexec/ld.elf_so/rtld.h: revision 1.89
	libexec/ld.elf_so/arch/x86_64/mdreloc.c: revision 1.36
	libexec/ld.elf_so/map_object.c: revision 1.41
	libexec/ld.elf_so/arch/x86_64/mdreloc.c: revision 1.37
	libexec/ld.elf_so/arch/sparc64/mdreloc.c: revision 1.46
	include/link_elf.h: revision 1.10
	libexec/ld.elf_so/arch/i386/mdreloc.c: revision 1.29
	libexec/ld.elf_so/arch/vax/mdreloc.c: revision 1.26
	libexec/ld.elf_so/arch/alpha/alpha_reloc.c: revision 1.34
	libexec/ld.elf_so/arch/hppa/hppa_reloc.c: revision 1.31
	libexec/ld.elf_so/arch/alpha/alpha_reloc.c: revision 1.35
	libexec/ld.elf_so/Makefile: revision 1.94
	libexec/ld.elf_so/arch/hppa/hppa_reloc.c: revision 1.32
	libexec/ld.elf_so/Makefile: revision 1.95
	libexec/ld.elf_so/arch/arm/mdreloc.c: revision 1.31
	libexec/ld.elf_so/Makefile: revision 1.96
	libexec/ld.elf_so/arch/arm/mdreloc.c: revision 1.32
	libexec/ld.elf_so/reloc.c: revision 1.98
	libexec/ld.elf_so/arch/arm/mdreloc.c: revision 1.33
	sys/sys/exec_elf.h: revision 1.106
	libexec/ld.elf_so/rtld.c: revision 1.130
	libexec/ld.elf_so/load.c: revision 1.37
	libexec/ld.elf_so/rtld.c: revision 1.131
	libexec/ld.elf_so/load.c: revision 1.38
	libexec/ld.elf_so/rtld.h: revision 1.90
	libexec/ld.elf_so/headers.c: revision 1.36
	libexec/ld.elf_so/rtld.h: revision 1.95
	libexec/ld.elf_so/arch/i386/mdreloc.c: revision 1.30
	libexec/ld.elf_so/arch/m68k/mdreloc.c: revision 1.25
	libexec/ld.elf_so/symbol.c: revision 1.50
	libexec/ld.elf_so/symbol.c: revision 1.51
	libexec/ld.elf_so/arch/sparc/mdreloc.c: revision 1.43
	libexec/ld.elf_so/symbol.c: revision 1.52
	libexec/ld.elf_so/arch/sh3/mdreloc.c: revision 1.27
	libexec/ld.elf_so/symbol.c: revision 1.54
PR/39240: Satoshi Suetake: Don't fail when attempting to resolve weak symbols
when we are doing immediate binding, leave them alone and they will be dealt
with later during lazy binding. From skrll@@
Implement negative cache checks for symbol lookups.
Uses the Donelist idea from FreeBSD.
Use alloca(3) instead of local xmalloc for creating our DoneLists.
This allows threaded programs to use us a little better, PR lib/43005.
Implement dl_iterate_phdr.
Somewhat taken from FreeBSD. Manual page from OpenBSD.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.43 2008/07/24 04:39:25 matt Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.43 2008/07/24 04:39:25 matt Exp $");
d476 1
a476 1
	if (err)
a513 1
	unsigned long info = rela->r_info;
d515 1
a515 1
	assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
d517 4
a520 2
	def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
	if (__predict_false(def == NULL))
a521 2
	if (__predict_false(def == &_rtld_sym_zero))
		return 0;
@


1.43.6.1
log
@Sync with HEAD.

Third (and last) commit. See http://mail-index.netbsd.org/source-changes/2009/05/13/msg221222.html
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.44 2009/03/16 02:46:48 lukem Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.44 2009/03/16 02:46:48 lukem Exp $");
d292 1
a292 1
	relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
@


1.42
log
@Remove clause 3 and 4 from TNF licenses
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.41 2007/02/23 01:17:11 matt Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.41 2007/02/23 01:17:11 matt Exp $");
d476 1
a476 1
	if (err)
@


1.42.2.1
log
@Sync with wrstuden-revivesa-base-2.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.42 2008/04/28 20:23:04 martin Exp $	*/
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.42 2008/04/28 20:23:04 martin Exp $");
d476 1
a476 1
	if (err || result == 0)
@


1.41
log
@Remove MD COMBRELOC support since it's now MI.
Enable COMBRELOC for all arches
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.40 2007/02/15 19:42:13 martin Exp $	*/
a18 7
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by the NetBSD
 *        Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
d35 1
a35 1
__RCSID("$NetBSD: mdreloc.c,v 1.40 2007/02/15 19:42:13 martin Exp $");
@


1.41.10.1
log
@sync with head.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.41 2007/02/23 01:17:11 matt Exp $	*/
d19 7
d42 1
a42 1
__RCSID("$NetBSD: mdreloc.c,v 1.41 2007/02/23 01:17:11 matt Exp $");
@


1.40
log
@Add COMBRELOC support
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.39 2006/05/10 21:53:15 mrg Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: mdreloc.c,v 1.39 2006/05/10 21:53:15 mrg Exp $");
a309 4
#define COMBRELOC
#ifdef COMBRELOC
	unsigned long lastsym = -1;
#endif
d356 4
a359 11
#ifdef COMBRELOC
			if (symnum != lastsym) {
#endif
				def = _rtld_find_symdef(symnum, obj, &defobj,
				    false);
				if (def == NULL)
					return -1;
#ifdef COMBRELOC
				lastsym = symnum;
			}
#endif
@


1.39
log
@quell GCC 4.1 uninitialised variable warnings.

XXX: we should audit the tree for which old ones are no longer needed
after getting the older compilers out of the tree..
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.38 2005/12/24 20:59:31 perry Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: mdreloc.c,v 1.38 2005/12/24 20:59:31 perry Exp $");
d310 6
a320 2
		const Elf_Sym *def = NULL;
		const Obj_Entry *defobj = NULL;
d360 11
a370 3
			def = _rtld_find_symdef(symnum, obj, &defobj, false);
			if (def == NULL)
				return (-1);
@


1.38
log
@Remove leading __ from __(const|inline|signed|volatile) -- it is obsolete.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.37 2005/08/20 19:01:17 skrll Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: mdreloc.c,v 1.37 2005/08/20 19:01:17 skrll Exp $");
d460 2
@


1.37
log
@Add __RCSID.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.36 2005/08/15 10:52:42 skrll Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD$");
d584 1
a584 1
		__asm __volatile("iflush %0+4" : : "r" (where));
d603 2
a604 2
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));
d625 3
a627 3
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));
d648 3
a650 3
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));
d672 4
a675 4
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));
d697 4
a700 4
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));
d724 6
a729 6
		__asm __volatile("iflush %0+24" : : "r" (where));
		__asm __volatile("iflush %0+20" : : "r" (where));
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));
@


1.36
log
@KNF
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.35 2005/01/05 09:16:03 martin Exp $	*/
d40 5
@


1.35
log
@Add LD_BIND_NOW support for sparc64.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.34 2003/07/24 10:12:29 skrll Exp $	*/
d225 3
a227 3
void _rtld_install_plt(Elf_Word *pltgot, Elf_Addr proc);
static inline int _rtld_relocate_plt_object(const Obj_Entry *obj,
    const Elf_Rela *rela, Elf_Addr *tp);
@


1.34
log
@ANSIfy and de-__P().
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.33 2003/05/23 20:13:50 petrov Exp $	*/
d226 2
d452 2
a453 4
	const Elf_Sym *def;
	const Obj_Entry *defobj;
	Elf_Word *where;
	Elf_Addr value, offset;
d474 39
a512 1
	where = (Elf_Word *)(obj->relocbase + rela->r_offset);
d520 1
a520 1
		_rtld_die();
d728 4
a731 1
	return (caddr_t)value;
@


1.33
log
@Fix alignment problem in debug output.
Happens only under RTLD_DEBUG_RELOC.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.32 2002/10/18 20:35:25 thorpej Exp $	*/
d211 1
a211 1
caddr_t _rtld_bind __P((const Obj_Entry *, Elf_Word));
d225 1
a225 1
void _rtld_install_plt __P((Elf_Word *pltgot,	Elf_Addr proc));
d228 1
a228 3
_rtld_install_plt(pltgot, proc)
	Elf_Word *pltgot;
	Elf_Addr proc;
d276 1
a276 3
_rtld_relocate_nonplt_self(dynp, relocbase)
	Elf_Dyn *dynp;
	Elf_Addr relocbase;
d300 1
a300 2
_rtld_relocate_nonplt_objects(obj)
	const Obj_Entry *obj;
d441 1
a441 2
_rtld_relocate_plt_lazy(obj)
	const Obj_Entry *obj;
d447 1
a447 3
_rtld_bind(obj, reloff)
	const Obj_Entry *obj;
	Elf_Word reloff;
@


1.32
log
@_rtld_bind(): Don't use "rela" until after we've (potentially) adjusted
it.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.31 2002/09/26 20:42:12 mycroft Exp $	*/
d435 1
a435 1
			    obj->path, (void *)*where, defobj->path));
d438 1
a438 1
			    obj->path, (void *)*where));
@


1.31
log
@Remove the `self' args to _rtld_relocate_objects() and
_rtld_relocate_nonplt_objects().
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.30 2002/09/26 02:25:57 mycroft Exp $	*/
d460 1
a460 1
	Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
d481 2
@


1.30
log
@Remove vestigal comments about _rtld_bind_start_0() -- it works now.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.29 2002/09/26 02:14:10 mycroft Exp $	*/
d304 1
a304 1
_rtld_relocate_nonplt_objects(obj, self)
a305 1
	bool self;
a307 3

	if (self)
		return (0);
@


1.29
log
@Make room for the argument save area in _rtld_start().  The PLT stub already
made room from _rtld_bind_start(), but add a comment explaining the instruction
it uses.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.28 2002/09/25 22:29:12 mycroft Exp $	*/
a240 16

#if 0
long _rtld_bind_start_0_stub __P((long x, long y));
long 
_rtld_bind_start_0_stub(y, x)
	long y, x;
{
	long i;
	long n;

	i = x - y + 8 - 32768*32;
	n = 32768 + (i/5120)*160 + (i%5120)/24;

	return (n);
}
#endif
@


1.28
log
@Add a comment explaining some of the magick.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.27 2002/09/25 22:25:11 mycroft Exp $	*/
d216 1
a216 1
#define	SAVE		0x9de3bf50
@


1.27
log
@Fix a bug that caused PLT entries to effectively not be patched.
Also, fix more bugs in the large-PLT case -- my test program works now.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.25 2002/09/25 14:36:37 mycroft Exp $	*/
d544 3
a546 1
		 * This entry is >32768.  Just replace the pointer.
@


1.26
log
@Swap registers %o0 and %o1 in the binder stub to say one instruction.

Fix an obvious bug in the 64-bit PLT fixup: the SLLX was by 12 bits, when it
should be 32.

Fix what *appear* to be two bugs in the >32768 PLT entry stub:
* One division was wrong (/14 rather than /24).
* We need to subtract 1048576 (to make the offset relative to the beginning of
  the upper section), not add it.
This path is still untested, and buggy.
@
text
@d9 1
a9 1
 * by Paul Kranenburg.
d480 1
a480 1
	Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
d511 2
a512 2
	rdbg(("bind now/fixup in %s --> old=%p new=%p", 
	    defobj->strtab + def->st_name, (void *)*where, (void *)value));
d546 1
a546 1
		ptr[0] = value;
@


1.25
log
@_rtld_bind_start_0_stub() is not actually used.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.24 2002/09/25 14:35:39 mycroft Exp $	*/
d204 3
a206 3
/* %hi(v) with variable shift */
#define	HIVAL(v, s)	(((v) >> (s)) &  0x003fffff)
#define LOVAL(v)	((v) & 0x000003ff)
d222 2
a223 2
#define	JMPL_l0_o1	0x93c42000
#define	MOV_g1_o0	0x90100001
d235 1
a235 1
	pltgot[3] = OR_l0_l0  | LOVAL((proc) >> 32);
d238 2
a239 2
	pltgot[6] = JMPL_l0_o1 | LOVAL(proc);
	pltgot[7] = MOV_g1_o0;
d245 2
a246 2
_rtld_bind_start_0_stub(x, y)
	long x, y;
d251 1
a251 1
	i = x - y + 1048596;
d568 1
a568 1
		 * We're withing 32-bits of address zero.
d582 1
a582 1
		where[2] = JMP   | LOVAL(value);
d589 1
a589 1
		 * We're withing 32-bits of address -1.
d612 1
a612 1
		 * We're withing 32-bits -- we can use a direct call insn 
d635 1
a635 1
		 * We're withing 44 bits.  We can generate this pattern:
d649 1
a649 1
		where[4] = JMP   | LOVAL(offset);
d660 1
a660 1
		 * We're withing 44 bits.  We can generate this pattern:
d674 1
a674 1
		where[4] = JMP   | LOVAL(offset);
d699 1
a699 1
		where[6] = JMP     | LOVAL(value);
d701 2
a702 2
		where[4] = SLLX    | 12;
		where[3] = OR      | LOVAL((value) >> 32);
d705 1
a706 1
		__asm __volatile("iflush %0+16" : : "r" (where));
@


1.24
log
@Push a multiple from _rtld_bind_start_[01]() to _rtld_bind().
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.23 2002/09/25 07:27:54 mycroft Exp $	*/
d242 1
d256 1
@


1.23
log
@Push the _rtld_bind() interface into MD code -- it's just a trivial wrapper
anyway.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.22 2002/09/24 13:59:31 mycroft Exp $	*/
d475 1
a475 1
	const Elf_Rela *rela = (const Elf_Rela *)((caddr_t)obj->pltrela + reloff);
@


1.22
log
@%ld -> %p
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.21 2002/09/12 22:56:31 mycroft Exp $	*/
d5 1
a5 1
 * Copyright (c) 1999 The NetBSD Foundation, Inc.
d211 1
a211 227

int
_rtld_relocate_plt_object(obj, rela, addrp)
	const Obj_Entry *obj;
	const Elf_Rela *rela;
	caddr_t *addrp;
{
	const Elf_Sym *def;
	const Obj_Entry *defobj;
	Elf_Word *where = (Elf_Word *)((Elf_Addr)obj->relocbase + rela->r_offset);
	Elf_Addr value, offset;

	/* Fully resolve procedure addresses now */

	assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));

	def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true);
	if (def == NULL)
		return (-1);

	value = (Elf_Addr) (defobj->relocbase + def->st_value);
	rdbg(("bind now/fixup in %s --> old=%p new=%p", 
	    defobj->strtab + def->st_name, (void *)*where, (void *)value));

	/*
	 * At the PLT entry pointed at by `where', we now construct
	 * a direct transfer to the now fully resolved function
	 * address.
	 *
	 * A PLT entry is supposed to start by looking like this:
	 *
	 *	sethi	%hi(. - .PLT0), %g1
	 *	ba,a	%xcc, .PLT1
	 *	nop
	 *	nop
	 *	nop
	 *	nop
	 *	nop
	 *	nop
	 *
	 * When we replace these entries we start from the second
	 * entry and do it in reverse order so the last thing we
	 * do is replace the branch.  That allows us to change this
	 * atomically.
	 *
	 * We now need to find out how far we need to jump.  We
	 * have a choice of several different relocation techniques
	 * which are increasingly expensive.
	 */

	offset = ((Elf_Addr)where) - value;
	if (rela->r_addend) {
		Elf_Addr *ptr = (Elf_Addr *)where;
		/*
		 * This entry is >32768.  Just replace the pointer.
		 */
		ptr[0] = value;

	} else if (offset <= (1L<<20) && offset >= -(1L<<20)) {
		/* 
		 * We're within 1MB -- we can use a direct branch insn.
		 *
		 * We can generate this pattern:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	ba,a	%xcc, addr
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[1] = BAA | ((offset >> 2) &0x3fffff);
		__asm __volatile("iflush %0+4" : : "r" (where));
	} else if (value >= 0 && value < (1L<<32)) {
		/* 
		 * We're withing 32-bits of address zero.
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%hi(addr), %g1
		 *	jmp	%g1+%lo(addr)
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[2] = JMP   | LOVAL(value);
		where[1] = SETHI | HIVAL(value, 10);
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	} else if (value <= 0 && value > -(1L<<32)) {
		/* 
		 * We're withing 32-bits of address -1.
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%hix(addr), %g1
		 *	xor	%g1, %lox(addr), %g1
		 *	jmp	%g1
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[3] = JMP;
		where[2] = XOR | ((~value) & 0x00001fff);
		where[1] = SETHI | HIVAL(~value, 10);
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	} else if (offset <= (1L<<32) && offset >= -((1L<<32) - 4)) {
		/* 
		 * We're withing 32-bits -- we can use a direct call insn 
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	mov	%o7, %g1
		 *	call	(.+offset)
		 *	 mov	%g1, %o7
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[3] = MOV17;
		where[2] = CALL	  | ((offset >> 4) & 0x3fffffff);
		where[1] = MOV71;
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	} else if (offset >= 0 && offset < (1L<<44)) {
		/* 
		 * We're withing 44 bits.  We can generate this pattern:
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%h44(addr), %g1
		 *	or	%g1, %m44(addr), %g1
		 *	sllx	%g1, 12, %g1	
		 *	jmp	%g1+%l44(addr)	
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[4] = JMP   | LOVAL(offset);
		where[3] = SLLX  | 12;
		where[2] = OR    | (((offset) >> 12) & 0x00001fff);
		where[1] = SETHI | HIVAL(offset, 22);
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	} else if (offset < 0 && offset > -(1L<<44)) {
		/* 
		 * We're withing 44 bits.  We can generate this pattern:
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%h44(-addr), %g1
		 *	xor	%g1, %m44(-addr), %g1
		 *	sllx	%g1, 12, %g1	
		 *	jmp	%g1+%l44(addr)	
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[4] = JMP   | LOVAL(offset);
		where[3] = SLLX  | 12;
		where[2] = XOR   | (((~offset) >> 12) & 0x00001fff);
		where[1] = SETHI | HIVAL(~offset, 22);
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	} else {
		/* 
		 * We need to load all 64-bits
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%hh(addr), %g1
		 *	sethi	%lm(addr), %g5
		 *	or	%g1, %hm(addr), %g1
		 *	sllx	%g1, 32, %g1
		 *	or	%g1, %g5, %g1
		 *	jmp	%g1+%lo(addr)
		 *	nop
		 *
		 */
		where[6] = JMP     | LOVAL(value);
		where[5] = ORG5;
		where[4] = SLLX    | 12;
		where[3] = OR      | LOVAL((value) >> 32);
		where[2] = SETHIG5 | HIVAL(value, 10);
		where[1] = SETHI   | HIVAL(value, 42);
		__asm __volatile("iflush %0+20" : : "r" (where));
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	}

	*addrp = (caddr_t)value;
	return (0);
}
d342 1
a342 1
		/* We do JMP_SLOTs in relocate_plt_object() below */
d468 245
@


1.21
log
@Nuke -DRTLD_RELOCATE_SELF and `dodebug' from orbit.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.20 2002/09/12 20:24:03 mycroft Exp $	*/
d232 2
a233 2
	rdbg(("bind now/fixup in %s --> old=%lx new=%lx", 
	    defobj->strtab + def->st_name, (u_long)*where, (u_long)value));
@


1.20
log
@Prototype different functions.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.19 2002/09/12 20:21:01 mycroft Exp $	*/
d213 1
a213 1
_rtld_relocate_plt_object(obj, rela, addrp, dodebug)
a216 1
	bool dodebug;
d232 2
a233 3
	rdbg(dodebug, ("bind now/fixup in %s --> old=%lx new=%lx", 
	    defobj->strtab + def->st_name,
	    (u_long)*where, (u_long)value));
d544 1
a544 1
_rtld_relocate_nonplt_objects(obj, self, dodebug)
a546 1
	bool dodebug;
d590 1
a590 1
			rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
d677 1
a677 2
			rdbg(dodebug, ("%s %s in %s --> %p in %s",
			    reloc_names[type],
d681 1
a681 2
			rdbg(dodebug, ("%s in %s --> %p",
			    reloc_names[type],
d690 1
a690 1
_rtld_relocate_plt_lazy(obj, dodebug)
a691 1
	bool dodebug;
@


1.19
log
@_rtld_bind_start() is not used in MI code, so declare it in the MD code.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.18 2002/09/11 19:46:41 mycroft Exp $	*/
d208 2
a209 1
void _rtld_bind_start(void);
a505 2
		extern void _rtld_bind_start_0 __P((long, long));
		extern void _rtld_bind_start_1 __P((long, long));
@


1.18
log
@Do self-relocation similar to sparc.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.17 2002/09/06 15:51:24 mycroft Exp $	*/
d208 1
@


1.17
log
@Expand the comment about the R_TYPE(RELATIVE) special-case, as it's not quite
obvious from the code.  Also, just do it all the time, as an optimization.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.16 2002/09/06 15:32:57 mycroft Exp $	*/
d208 2
d519 26
d553 3
d589 1
a589 3
		 * Handle relative relocs here, because we might not be able to
		 * access the reloc_target_{flags,bitmask}[] tables while
		 * relocating ourself.
a591 1
			/* XXXX -- apparently we ignore the preexisting value */
d593 2
d680 1
a680 1
			rdbg(dodebug, ("%s %s in %s --> %p %s",
d683 1
a683 1
			    obj->path, (void *)value, defobj->path));
d685 3
a687 2
			rdbg(dodebug, ("%s --> %p", reloc_names[type],
			    (void *)value));
@


1.16
log
@Make the reloc tables const.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.15 2002/09/06 15:17:59 mycroft Exp $	*/
d558 3
a560 2
		 * Handle relative relocs here, because we might not
		 * be able to access globals yet.
d562 1
a562 1
		if (self && type == R_TYPE(RELATIVE)) {
@


1.15
log
@Pass down an additional flag to _rtld_relocate_nonplt_objects() which
indicates whether we're relocating ld.elf_so itself.  Use this in some places
rather than hackish tests on `dodebug'.  (The Alpha and HPPA `dodebug' tests
were actually noops, because RTLD_RELOCATE_SELF is not set, and therefore
dodebug is always true.)
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.14 2002/09/06 03:12:08 mycroft Exp $	*/
d73 1
a73 1
static int reloc_target_flags[] = {
d157 1
a157 1
static long reloc_target_bitmask[] = {
@


1.14
log
@Re-poison a lot of consts, now that the mark shite is gone.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.13 2002/09/06 03:05:37 mycroft Exp $	*/
d518 1
a518 1
_rtld_relocate_nonplt_objects(obj, dodebug)
d520 1
d561 1
a561 1
		if (!dodebug && type == R_TYPE(RELATIVE)) {
@


1.13
log
@Split _rtld_relocate_plt_object() into two MD functions:
* _rtld_relocate_plt_lazy() fixes up all the relocs pointing to the PLT.  (On
  most platforms it just does a simple base-relative fixup; on SPARC it does
  nothing.)
* _rtld_relocate_plt_object() does immediate binding for a PLT entry.
The basic gist is that this saves a bit of time on SPARC (where the iteration
through the pltrela table was gratuitous), and a little less time on all other
platforms.  A whole lot of #ifdef'ed crap is moved out of reloc.c, too.

NOT tested on: hppa sh x86_64
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.12 2002/09/06 02:01:40 mycroft Exp $	*/
d210 1
a210 1
	Obj_Entry *obj;
d519 1
a519 1
	Obj_Entry *obj;
d663 1
a663 1
	Obj_Entry *obj;
@


1.12
log
@Repair a slight biff I made earlier -- do not exit the loop in
_rtld_relocate_nonplt_objects() early.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.11 2002/09/05 21:31:35 mycroft Exp $	*/
d209 1
a209 1
_rtld_relocate_plt_object(obj, rela, addrp, bind_now, dodebug)
a212 1
	bool bind_now;
a219 3
	if (bind_now == 0 && obj->pltgot != NULL)
		return (0);

d229 2
a230 2
	rdbg(dodebug, ("bind now %d/fixup in %s --> old=%lx new=%lx", 
	    (int)bind_now, defobj->strtab + def->st_name,
d433 1
a433 3
	if (addrp != NULL)
		*addrp = (caddr_t)value;

d658 8
@


1.11
log
@Partially fix up some debug printf()s that don't need to use defobj.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.10 2002/09/05 21:21:12 mycroft Exp $	*/
d543 1
a543 1
			return (0);
d547 1
a547 1
			return (0);
d551 1
a551 1
			return (0);
d569 1
a569 1
			return (0);
@


1.10
log
@A few things:
* Pass a symbol number to _rtld_find_symdef(), not a r_info.
* Don't try to do a symbol lookup when we find an unsupported relocation;
  instead get the symbol name from the referencing object's strtab.
* Add preliminary support for `-z combreloc'-style startup optimization on
  i386, `#ifdef COMBRELOC'.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.9 2002/09/05 20:08:19 mycroft Exp $	*/
d656 3
a658 4
			    defobj->strtab + def->st_name, obj->path,
			    (void *)value, defobj->path));
		}
		else {
@


1.9
log
@Rename _rtld_relocate_nonplt_object() to _rtld_relocate_nonplt_objects(),
and push the outer loop into it.  This actually shaves a couple % off startup
time at least on PCs.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.8 2002/09/05 18:25:47 mycroft Exp $	*/
d228 1
a228 1
	def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
d536 1
d539 1
d575 1
a575 2
			def = _rtld_find_symdef(rela->r_info, obj, &defobj,
			    false);
@


1.8
log
@Split _rtld_relocate_nonplt_object() into separate MD files.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.7 2002/09/05 16:33:58 junyoung Exp $	*/
d524 1
a524 1
_rtld_relocate_nonplt_object(obj, rela, dodebug)
a525 1
	const Elf_Rela *rela;
d528 1
a528 5
	Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
	Elf_Word type;
	Elf_Addr value = 0, mask;
	const Elf_Sym *def = NULL;
	const Obj_Entry *defobj = NULL;
d530 20
a549 3
	type = ELF_R_TYPE(rela->r_info);
	if (type == R_TYPE(NONE))
		return (0);
d551 6
a556 3
	/* We do JMP_SLOTs in relocate_plt_object() below */
	if (type == R_TYPE(JMP_SLOT))
		return (0);
d558 1
a558 3
	/* COPY relocs are also handled elsewhere */
	if (type == R_TYPE(COPY))
		return (0);
d560 9
a568 6
	/*
	 * We use the fact that relocation types are an `enum'
	 * Note: R_SPARC_UA16 is currently numerically largest.
	 */
	if (type > R_TYPE(UA16))
		return (-1);
d570 1
a570 1
	value = rela->r_addend;
d572 5
a576 9
	/*
	 * Handle relative relocs here, because we might not
	 * be able to access globals yet.
	 */
	if (!dodebug && type == R_TYPE(RELATIVE)) {
		/* XXXX -- apparently we ignore the preexisting value */
		*where = (Elf_Addr)(obj->relocbase + value);
		return (0);
	}
d578 3
a580 1
	if (RELOC_RESOLVE_SYMBOL(type)) {
d582 3
a584 12
		/* Find the symbol */
		def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
		if (def == NULL)
			return (-1);

		/* Add in the symbol's absolute address */
		value += (Elf_Addr)(defobj->relocbase + def->st_value);
	}

	if (RELOC_PC_RELATIVE(type)) {
		value -= (Elf_Addr)where;
	}
d586 13
a598 11
	if (RELOC_BASE_RELATIVE(type)) {
		/*
		 * Note that even though sparcs use `Elf_rela' exclusively
		 * we still need the implicit memory addend in relocations
		 * referring to GOT entries. Undoubtedly, someone f*cked
		 * this up in the distant past, and now we're stuck with
		 * it in the name of compatibility for all eternity..
		 *
		 * In any case, the implicit and explicit should be mutually
		 * exclusive. We provide a check for that here.
		 */
d600 9
a608 5
		if (value != 0 && *where != 0) {
			xprintf("BASE_REL(%s): where=%p, *where 0x%lx, "
				"addend=0x%lx, base %p\n",
				obj->path, where, *where,
				rela->r_addend, obj->relocbase);
a609 4
#endif
		/* XXXX -- apparently we ignore the preexisting value */
		value += (Elf_Addr)(obj->relocbase);
	}
d611 20
a630 20
	mask = RELOC_VALUE_BITMASK(type);
	value >>= RELOC_VALUE_RIGHTSHIFT(type);
	value &= mask;

	if (RELOC_UNALIGNED(type)) {
		/* Handle unaligned relocations. */
		Elf_Addr tmp = 0;
		char *ptr = (char *)where;
		int i, size = RELOC_TARGET_SIZE(type)/8;
		
		/* Read it in one byte at a time. */
		for (i=0; i<size; i++)
			tmp = (tmp << 8) | ptr[i];

		tmp &= ~mask;
		tmp |= value;

		/* Write it back out. */
		for (i=0; i<size; i++)
			ptr[i] = ((tmp >> (8*i)) & 0xff);
d632 1
a632 1
		value = (Elf_Addr)tmp;
d635 3
a637 3
	} else if (RELOC_TARGET_SIZE(type) > 32) {
		*where &= ~mask;
		*where |= value;
d639 1
a639 1
		value = (Elf_Addr)*where;
d641 2
a642 2
	} else {
		Elf32_Addr *where32 = (Elf32_Addr *)where;
d644 2
a645 2
		*where32 &= ~mask;
		*where32 |= value;
d647 1
a647 1
		value = (Elf_Addr)*where32;
d649 1
a649 1
	}
d652 11
a662 5
	if (RELOC_RESOLVE_SYMBOL(type)) {
		rdbg(dodebug, ("%s %s in %s --> %p %s", 
		    reloc_names[type],
		    defobj->strtab + def->st_name, obj->path,
		    (void *)value, defobj->path));
a663 5
	else {
		rdbg(dodebug, ("%s --> %p", reloc_names[type],
		    (void *)value));
	}
#endif
@


1.7
log
@Remove unused arguments of _rtld_find_symdef().
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.6 2002/09/05 15:38:31 mycroft Exp $	*/
a186 137

int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
	Obj_Entry *obj;
	const Elf_Rela *rela;
	bool dodebug;
{
	Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
	Elf_Word type;
	Elf_Addr value = 0, mask;
	const Elf_Sym *def = NULL;
	const Obj_Entry *defobj = NULL;

	type = ELF_R_TYPE(rela->r_info);
	if (type == R_TYPE(NONE))
		return (0);

	/* We do JMP_SLOTs in relocate_plt_object() below */
	if (type == R_TYPE(JMP_SLOT))
		return (0);

	/* COPY relocs are also handled elsewhere */
	if (type == R_TYPE(COPY))
		return (0);

	/*
	 * We use the fact that relocation types are an `enum'
	 * Note: R_SPARC_UA16 is currently numerically largest.
	 */
	if (type > R_TYPE(UA16))
		return (-1);

	value = rela->r_addend;

	/*
	 * Handle relative relocs here, because we might not
	 * be able to access globals yet.
	 */
	if (!dodebug && type == R_TYPE(RELATIVE)) {
		/* XXXX -- apparently we ignore the preexisting value */
		*where = (Elf_Addr)(obj->relocbase + value);
		return (0);
	}

	if (RELOC_RESOLVE_SYMBOL(type)) {

		/* Find the symbol */
		def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
		if (def == NULL)
			return (-1);

		/* Add in the symbol's absolute address */
		value += (Elf_Addr)(defobj->relocbase + def->st_value);
	}

	if (RELOC_PC_RELATIVE(type)) {
		value -= (Elf_Addr)where;
	}

	if (RELOC_BASE_RELATIVE(type)) {
		/*
		 * Note that even though sparcs use `Elf_rela' exclusively
		 * we still need the implicit memory addend in relocations
		 * referring to GOT entries. Undoubtedly, someone f*cked
		 * this up in the distant past, and now we're stuck with
		 * it in the name of compatibility for all eternity..
		 *
		 * In any case, the implicit and explicit should be mutually
		 * exclusive. We provide a check for that here.
		 */
#ifdef DIAGNOSTIC
		if (value != 0 && *where != 0) {
			xprintf("BASE_REL(%s): where=%p, *where 0x%lx, "
				"addend=0x%lx, base %p\n",
				obj->path, where, *where,
				rela->r_addend, obj->relocbase);
		}
#endif
		/* XXXX -- apparently we ignore the preexisting value */
		value += (Elf_Addr)(obj->relocbase);
	}

	mask = RELOC_VALUE_BITMASK(type);
	value >>= RELOC_VALUE_RIGHTSHIFT(type);
	value &= mask;

	if (RELOC_UNALIGNED(type)) {
		/* Handle unaligned relocations. */
		Elf_Addr tmp = 0;
		char *ptr = (char *)where;
		int i, size = RELOC_TARGET_SIZE(type)/8;
		
		/* Read it in one byte at a time. */
		for (i=0; i<size; i++)
			tmp = (tmp << 8) | ptr[i];

		tmp &= ~mask;
		tmp |= value;

		/* Write it back out. */
		for (i=0; i<size; i++)
			ptr[i] = ((tmp >> (8*i)) & 0xff);
#ifdef RTLD_DEBUG_RELOC
		value = (Elf_Addr)tmp;
#endif

	} else if (RELOC_TARGET_SIZE(type) > 32) {
		*where &= ~mask;
		*where |= value;
#ifdef RTLD_DEBUG_RELOC
		value = (Elf_Addr)*where;
#endif
	} else {
		Elf32_Addr *where32 = (Elf32_Addr *)where;

		*where32 &= ~mask;
		*where32 |= value;
#ifdef RTLD_DEBUG_RELOC
		value = (Elf_Addr)*where32;
#endif
	}

#ifdef RTLD_DEBUG_RELOC
	if (RELOC_RESOLVE_SYMBOL(type)) {
		rdbg(dodebug, ("%s %s in %s --> %p %s", 
		    reloc_names[type],
		    defobj->strtab + def->st_name, obj->path,
		    (void *)value, defobj->path));
	}
	else {
		rdbg(dodebug, ("%s --> %p", reloc_names[type],
		    (void *)value));
	}
#endif
	return (0);
}

d521 136
@


1.6
log
@Make _rtld_setup_pltgot() a consistent interface on all platforms.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.5 2001/04/25 12:24:51 kleink Exp $	*/
d234 1
a234 2
		def = _rtld_find_symdef(_rtld_objlist, rela->r_info,
					NULL, obj, &defobj, false);
d365 1
a365 2
	def = _rtld_find_symdef(_rtld_objlist, rela->r_info,
				NULL, obj, &defobj, true);
@


1.5
log
@Sync with <sys/exec_elf.h> rev. 1.45: ElfNN_RelA -> ElfNN_Rela.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.4 2000/09/16 14:04:30 eeh Exp $	*/
d625 36
@


1.5.2.1
log
@Apply patch (request by skrll in ticket #1702):
Bring "ld.elf_so" (mostly) in sync with NetBSD-current:
- MI and MD (e.g. under NetBSD-alpha) performance improvements
- RTLD_SELF, RTLD_NEXT, RTLD_DEFAULT support
- much better structured code
- closes PR bin/25464
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.34 2003/07/24 10:12:29 skrll Exp $	*/
d5 1
a5 1
 * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
d9 1
a9 1
 * by Paul Kranenburg and by Charles M. Hannum.
d73 1
a73 1
static const int reloc_target_flags[] = {
d157 1
a157 1
static const long reloc_target_bitmask[] = {
a186 15
/*
 * Instruction templates:
 */
#define	BAA	0x10400000	/*	ba,a	%xcc, 0 */
#define	SETHI	0x03000000	/*	sethi	%hi(0), %g1 */
#define	JMP	0x81c06000	/*	jmpl	%g1+%lo(0), %g0 */
#define	NOP	0x01000000	/*	sethi	%hi(0), %g0 */
#define	OR	0x82806000	/*	or	%g1, 0, %g1 */
#define	XOR	0x82c06000	/*	xor	%g1, 0, %g1 */
#define	MOV71	0x8283a000	/*	or	%o7, 0, %g1 */
#define	MOV17	0x9c806000	/*	or	%g1, 0, %o7 */
#define	CALL	0x40000000	/*	call	0 */
#define	SLLX	0x8b407000	/*	sllx	%g1, 0, %g1 */
#define	SETHIG5	0x0b000000	/*	sethi	%hi(0), %g5 */
#define	ORG5	0x82804005	/*	or	%g1, %g5, %g1 */
d188 5
a192 26

/* %hi(v)/%lo(v) with variable shift */
#define	HIVAL(v, s)	(((v) >> (s)) & 0x003fffff)
#define LOVAL(v, s)	(((v) >> (s)) & 0x000003ff)

void _rtld_bind_start_0(long, long);
void _rtld_bind_start_1(long, long);
void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);

/*
 * Install rtld function call into this PLT slot.
 */
#define	SAVE		0x9de3bf50	/* i.e. `save %sp,-176,%sp' */
#define	SETHI_l0	0x21000000
#define	SETHI_l1	0x23000000
#define	OR_l0_l0	0xa0142000
#define	SLLX_l0_32_l0	0xa12c3020
#define	OR_l0_l1_l0	0xa0140011
#define	JMPL_l0_o0	0x91c42000
#define	MOV_g1_o1	0x92100001

void _rtld_install_plt(Elf_Word *pltgot, Elf_Addr proc);

void
_rtld_install_plt(Elf_Word *pltgot, Elf_Addr proc)
d194 17
a210 9
	pltgot[0] = SAVE;
	pltgot[1] = SETHI_l0  | HIVAL(proc, 42);
	pltgot[2] = SETHI_l1  | HIVAL(proc, 10);
	pltgot[3] = OR_l0_l0  | LOVAL(proc, 32);
	pltgot[4] = SLLX_l0_32_l0;
	pltgot[5] = OR_l0_l1_l0;
	pltgot[6] = JMPL_l0_o0 | LOVAL(proc, 0);
	pltgot[7] = MOV_g1_o1;
}
a211 3
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
d213 2
a214 15
	 * On sparc64 we got troubles.
	 *
	 * Instructions are 4 bytes long.
	 * Elf[64]_Addr is 8 bytes long, so are our pltglot[]
	 * array entries.
	 * Each PLT entry jumps to PLT0 to enter the dynamic
	 * linker.
	 * Loading an arbitrary 64-bit pointer takes 6
	 * instructions and 2 registers.
	 *
	 * Somehow we need to issue a save to get a new stack
	 * frame, load the address of the dynamic linker, and
	 * jump there, in 8 instructions or less.
	 *
	 * Oh, we need to fill out both PLT0 and PLT1.
d216 2
a217 2
	{
		Elf_Word *entry = (Elf_Word *)obj->pltgot;
d219 1
a219 3
		/* Install in entries 0 and 1 */
		_rtld_install_plt(&entry[0], (Elf_Addr) &_rtld_bind_start_0);
		_rtld_install_plt(&entry[8], (Elf_Addr) &_rtld_bind_start_1);
d221 8
a228 29
		/* 
		 * Install the object reference in first slot
		 * of entry 2.
		 */
		obj->pltgot[8] = (Elf_Addr) obj;
	}
}

void
_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
{
	const Elf_Rela *rela = 0, *relalim;
	Elf_Addr relasz = 0;
	Elf_Addr *where;

	for (; dynp->d_tag != DT_NULL; dynp++) {
		switch (dynp->d_tag) {
		case DT_RELA:
			rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
			break;
		case DT_RELASZ:
			relasz = dynp->d_un.d_val;
			break;
		}
	}
	relalim = (const Elf_Rela *)((caddr_t)rela + relasz);
	for (; rela < relalim; rela++) {
		where = (Elf_Addr *)(relocbase + rela->r_offset);
		*where = (Elf_Addr)(relocbase + rela->r_addend);
a229 6
}

int
_rtld_relocate_nonplt_objects(const Obj_Entry *obj)
{
	const Elf_Rela *rela;
d231 1
a231 22
	for (rela = obj->rela; rela < obj->relalim; rela++) {
		Elf_Addr *where;
		Elf_Word type;
		Elf_Addr value = 0, mask;
		const Elf_Sym *def = NULL;
		const Obj_Entry *defobj = NULL;
		unsigned long	 symnum;

		where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
		symnum = ELF_R_SYM(rela->r_info);

		type = ELF_R_TYPE(rela->r_info);
		if (type == R_TYPE(NONE))
			continue;

		/* We do JMP_SLOTs in _rtld_bind() below */
		if (type == R_TYPE(JMP_SLOT))
			continue;

		/* COPY relocs are also handled elsewhere */
		if (type == R_TYPE(COPY))
			continue;
d233 4
a236 5
		/*
		 * We use the fact that relocation types are an `enum'
		 * Note: R_SPARC_UA16 is currently numerically largest.
		 */
		if (type > R_TYPE(UA16))
d239 3
a241 1
		value = rela->r_addend;
d243 5
d249 8
a256 1
		 * Handle relative relocs here, as an optimization.
d258 6
a263 16
		if (type == R_TYPE(RELATIVE)) {
			*where = (Elf_Addr)(obj->relocbase + value);
			rdbg(("RELATIVE in %s --> %p", obj->path,
			    (void *)*where));
			continue;
		}

		if (RELOC_RESOLVE_SYMBOL(type)) {

			/* Find the symbol */
			def = _rtld_find_symdef(symnum, obj, &defobj, false);
			if (def == NULL)
				return (-1);

			/* Add in the symbol's absolute address */
			value += (Elf_Addr)(defobj->relocbase + def->st_value);
a264 25

		if (RELOC_PC_RELATIVE(type)) {
			value -= (Elf_Addr)where;
		}

		if (RELOC_BASE_RELATIVE(type)) {
			/*
			 * Note that even though sparcs use `Elf_rela'
			 * exclusively we still need the implicit memory addend
			 * in relocations referring to GOT entries.
			 * Undoubtedly, someone f*cked this up in the distant
			 * past, and now we're stuck with it in the name of
			 * compatibility for all eternity..
			 *
			 * In any case, the implicit and explicit should be
			 * mutually exclusive. We provide a check for that
			 * here.
			 */
#ifdef DIAGNOSTIC
			if (value != 0 && *where != 0) {
				xprintf("BASE_REL(%s): where=%p, *where 0x%lx, "
					"addend=0x%lx, base %p\n",
					obj->path, where, *where,
					rela->r_addend, obj->relocbase);
			}
d266 3
a268 3
			/* XXXX -- apparently we ignore the preexisting value */
			value += (Elf_Addr)(obj->relocbase);
		}
d270 20
a289 20
		mask = RELOC_VALUE_BITMASK(type);
		value >>= RELOC_VALUE_RIGHTSHIFT(type);
		value &= mask;

		if (RELOC_UNALIGNED(type)) {
			/* Handle unaligned relocations. */
			Elf_Addr tmp = 0;
			char *ptr = (char *)where;
			int i, size = RELOC_TARGET_SIZE(type)/8;

			/* Read it in one byte at a time. */
			for (i=0; i<size; i++)
				tmp = (tmp << 8) | ptr[i];

			tmp &= ~mask;
			tmp |= value;

			/* Write it back out. */
			for (i=0; i<size; i++)
				ptr[i] = ((tmp >> (8*i)) & 0xff);
d291 1
a291 1
			value = (Elf_Addr)tmp;
d294 3
a296 3
		} else if (RELOC_TARGET_SIZE(type) > 32) {
			*where &= ~mask;
			*where |= value;
d298 1
a298 1
			value = (Elf_Addr)*where;
d300 2
a301 2
		} else {
			Elf32_Addr *where32 = (Elf32_Addr *)where;
d303 2
a304 2
			*where32 &= ~mask;
			*where32 |= value;
d306 1
a306 1
			value = (Elf_Addr)*where32;
d308 1
a308 1
		}
d311 10
a320 8
		if (RELOC_RESOLVE_SYMBOL(type)) {
			rdbg(("%s %s in %s --> %p in %s", reloc_names[type],
			    obj->strtab + obj->symtab[symnum].st_name,
			    obj->path, (void *)value, defobj->path));
		} else {
			rdbg(("%s in %s --> %p", reloc_names[type],
			    obj->path, (void *)value));
		}
a321 1
	}
d325 21
d347 6
a352 7
_rtld_relocate_plt_lazy(const Obj_Entry *obj)
{
	return (0);
}

caddr_t
_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
a353 1
	const Elf_Rela *rela = obj->pltrela + reloff;
d356 1
a356 1
	Elf_Word *where;
d359 2
a360 20
	if (ELF_R_TYPE(obj->pltrela->r_info) == R_TYPE(JMP_SLOT)) {
		/*
		 * XXXX
		 *
		 * The first four PLT entries are reserved.  There is some
		 * disagreement whether they should have associated relocation
		 * entries.  Both the SPARC 32-bit and 64-bit ELF
		 * specifications say that they should have relocation entries,
		 * but the 32-bit SPARC binutils do not generate them, and now
		 * the 64-bit SPARC binutils have stopped generating them too.
		 * 
		 * So, to provide binary compatibility, we will check the first
		 * entry, if it is reserved it should not be of the type
		 * JMP_SLOT.  If it is JMP_SLOT, then the 4 reserved entries
		 * were not generated and our index is 4 entries too far.
		 */
		rela -= 4;
	}

	where = (Elf_Word *)(obj->relocbase + rela->r_offset);
d366 2
a367 1
	def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true);
d369 1
a369 1
		_rtld_die();
d371 4
a374 3
	value = (Elf_Addr)(defobj->relocbase + def->st_value);
	rdbg(("bind now/fixup in %s --> new=%p", 
	    defobj->strtab + def->st_name, (void *)value));
d406 1
a406 3
		 * This entry is >=32768.  The relocations points to a
		 * PC-relative pointer to the bind_0 stub at the top of the
		 * PLT section.  Update it to point to the target function.
d408 1
a408 1
		ptr[0] += value - (Elf_Addr)obj->pltgot;
d430 1
a430 1
		 * We're within 32-bits of address zero.
d444 1
a444 1
		where[2] = JMP   | LOVAL(value, 0);
d451 1
a451 1
		 * We're within 32-bits of address -1.
d474 1
a474 1
		 * We're within 32-bits -- we can use a direct call insn 
d497 1
a497 1
		 * We're within 44 bits.  We can generate this pattern:
d511 1
a511 1
		where[4] = JMP   | LOVAL(offset, 0);
d522 1
a522 1
		 * We're within 44 bits.  We can generate this pattern:
d536 1
a536 1
		where[4] = JMP   | LOVAL(offset, 0);
d561 1
a561 1
		where[6] = JMP     | LOVAL(value, 0);
d563 2
a564 2
		where[4] = SLLX    | 32;
		where[3] = OR      | LOVAL(value, 32);
a566 1
		__asm __volatile("iflush %0+24" : : "r" (where));
d569 1
d576 47
a622 1
	return (caddr_t)value;
d624 1
@


1.4
log
@Wrong register in machine code description.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.3 2000/07/26 02:07:36 mycroft Exp $	*/
d191 1
a191 1
	const Elf_RelA *rela;
d349 1
a349 1
	const Elf_RelA *rela;
@


1.3
log
@Catch up with type changes.  Also:
* Apply DT_PLTRELSZ to (one of) pltrel or pltrela *after* we've finished
  parsing the headers, so we know which one.
* Fix sparc64 bogons.  (It works now!)
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.2 2000/07/18 22:33:56 eeh Exp $	*/
d591 1
a591 1
#define	JMPL_l0_o0	0x93c42000
d607 1
a607 1
	pltgot[6] = JMPL_l0_o0 | LOVAL(proc);
@


1.3.2.1
log
@file mdreloc.c was added on branch netbsd-1-5 on 2000-07-26 23:45:23 +0000
@
text
@d1 624
@


1.3.2.2
log
@Approved by thorpej:
Add support for sparc64, including MD code and variable page size support.
Modify some variable types to insure they are the correct width on sparc64.

basesrc/libexec/ld.elf_so/arch/sparc64/Makefile.inc	0 -> 1.1
basesrc/libexec/ld.elf_so/arch/sparc64/mdreloc.c	0 -> 1.3
basesrc/libexec/ld.elf_so/arch/sparc64/rtld_start.S	0 -> 1.2
basesrc/libexec/ld.elf_so/headers.c			1.6 -> 1.8
basesrc/libexec/ld.elf_so/reloc.c			1.26 -> 1.27
basesrc/libexec/ld.elf_so/reloc.c			1.29 -> 1.31
basesrc/libexec/ld.elf_so/rtld.c			1.34 -> 1.35
basesrc/libexec/ld.elf_so/rtld.c			1.36 -> 1.40
basesrc/libexec/ld.elf_so/rtld.h			1.26 -> 1.27
basesrc/libexec/ld.elf_so/symbol.c			1.7 -> 1.9
@
text
@a0 624
/*	$NetBSD: mdreloc.c,v 1.3.2.1 2000/07/26 23:45:23 mycroft Exp $	*/

/*-
 * Copyright (c) 2000 Eduardo Horvath.
 * Copyright (c) 1999 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Paul Kranenburg.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by the NetBSD
 *        Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>

#include "rtldenv.h"
#include "debug.h"
#include "rtld.h"

/*
 * The following table holds for each relocation type:
 *	- the width in bits of the memory location the relocation
 *	  applies to (not currently used)
 *	- the number of bits the relocation value must be shifted to the
 *	  right (i.e. discard least significant bits) to fit into
 *	  the appropriate field in the instruction word.
 *	- flags indicating whether
 *		* the relocation involves a symbol
 *		* the relocation is relative to the current position
 *		* the relocation is for a GOT entry
 *		* the relocation is relative to the load address
 *
 */
#define _RF_S		0x80000000		/* Resolve symbol */
#define _RF_A		0x40000000		/* Use addend */
#define _RF_P		0x20000000		/* Location relative */
#define _RF_G		0x10000000		/* GOT offset */
#define _RF_B		0x08000000		/* Load address relative */
#define _RF_U		0x04000000		/* Unaligned */
#define _RF_SZ(s)	(((s) & 0xff) << 8)	/* memory target size */
#define _RF_RS(s)	( (s) & 0xff)		/* right shift */
static int reloc_target_flags[] = {
	0,							/* NONE */
	_RF_S|_RF_A|		_RF_SZ(8)  | _RF_RS(0),		/* RELOC_8 */
	_RF_S|_RF_A|		_RF_SZ(16) | _RF_RS(0),		/* RELOC_16 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* RELOC_32 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(8)  | _RF_RS(0),		/* DISP_8 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(16) | _RF_RS(0),		/* DISP_16 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* DISP_32 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP_30 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP_22 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(10),	/* HI22 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 22 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 13 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* LO10 */
	_RF_G|			_RF_SZ(32) | _RF_RS(0),		/* GOT10 */
	_RF_G|			_RF_SZ(32) | _RF_RS(0),		/* GOT13 */
	_RF_G|			_RF_SZ(32) | _RF_RS(10),	/* GOT22 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* PC10 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(10),	/* PC22 */
	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WPLT30 */
				_RF_SZ(32) | _RF_RS(0),		/* COPY */
	_RF_S|_RF_A|		_RF_SZ(64) | _RF_RS(0),		/* GLOB_DAT */
				_RF_SZ(32) | _RF_RS(0),		/* JMP_SLOT */
	      _RF_A|	_RF_B|	_RF_SZ(64) | _RF_RS(0),		/* RELATIVE */
	_RF_S|_RF_A|	_RF_U|	_RF_SZ(32) | _RF_RS(0),		/* UA_32 */

	      _RF_A|		_RF_SZ(32) | _RF_RS(0),		/* PLT32 */
	      _RF_A|		_RF_SZ(32) | _RF_RS(10),	/* HIPLT22 */
	      _RF_A|		_RF_SZ(32) | _RF_RS(0),		/* LOPLT10 */
	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* PCPLT32 */
	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(10),	/* PCPLT22 */
	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* PCPLT10 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 10 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 11 */
	_RF_S|_RF_A|		_RF_SZ(64) | _RF_RS(0),		/* 64 */
	_RF_S|_RF_A|/*extra*/	_RF_SZ(32) | _RF_RS(0),		/* OLO10 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(42),	/* HH22 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(32),	/* HM10 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(10),	/* LM22 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(42),	/* PC_HH22 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(32),	/* PC_HM10 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(10),	/* PC_LM22 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP16 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP19 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* GLOB_JMP */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 7 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 5 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 6 */
	_RF_S|_RF_A|_RF_P|	_RF_SZ(64) | _RF_RS(0),		/* DISP64 */
	      _RF_A|		_RF_SZ(64) | _RF_RS(0),		/* PLT64 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(10),	/* HIX22 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* LOX10 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(22),	/* H44 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(12),	/* M44 */
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* L44 */
	_RF_S|_RF_A|		_RF_SZ(64) | _RF_RS(0),		/* REGISTER */
	_RF_S|_RF_A|	_RF_U|	_RF_SZ(64) | _RF_RS(0),		/* UA64 */
	_RF_S|_RF_A|	_RF_U|	_RF_SZ(16) | _RF_RS(0),		/* UA16 */
};

#ifdef RTLD_DEBUG_RELOC
static const char *reloc_names[] = {
	"NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8",
	"DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22",
	"22", "13", "LO10", "GOT10", "GOT13",
	"GOT22", "PC10", "PC22", "WPLT30", "COPY",
	"GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32", "PLT32",
	"HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", "PCPLT32",
	"10", "11", "64", "OLO10", "HH22",
	"HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22", 
	"WDISP16", "WDISP19", "GLOB_JMP", "7", "5", "6",
	"DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44", 
	"L44", "REGISTER", "UA64", "UA16"
};
#endif

#define RELOC_RESOLVE_SYMBOL(t)		((reloc_target_flags[t] & _RF_S) != 0)
#define RELOC_PC_RELATIVE(t)		((reloc_target_flags[t] & _RF_P) != 0)
#define RELOC_BASE_RELATIVE(t)		((reloc_target_flags[t] & _RF_B) != 0)
#define RELOC_UNALIGNED(t)		((reloc_target_flags[t] & _RF_U) != 0)
#define RELOC_USE_ADDEND(t)		((reloc_target_flags[t] & _RF_A) != 0)
#define RELOC_TARGET_SIZE(t)		((reloc_target_flags[t] >> 8) & 0xff)
#define RELOC_VALUE_RIGHTSHIFT(t)	(reloc_target_flags[t] & 0xff)

static long reloc_target_bitmask[] = {
#define _BM(x)	(~(-(1ULL << (x))))
	0,				/* NONE */
	_BM(8), _BM(16), _BM(32),	/* RELOC_8, _16, _32 */
	_BM(8), _BM(16), _BM(32),	/* DISP8, DISP16, DISP32 */
	_BM(30), _BM(22),		/* WDISP30, WDISP22 */
	_BM(22), _BM(22),		/* HI22, _22 */
	_BM(13), _BM(10),		/* RELOC_13, _LO10 */
	_BM(10), _BM(13), _BM(22),	/* GOT10, GOT13, GOT22 */
	_BM(10), _BM(22),		/* _PC10, _PC22 */  
	_BM(30), 0,			/* _WPLT30, _COPY */
	_BM(32), _BM(32), _BM(32),	/* _GLOB_DAT, JMP_SLOT, _RELATIVE */
	_BM(32), _BM(32),		/* _UA32, PLT32 */
	_BM(22), _BM(10),		/* _HIPLT22, LOPLT10 */
	_BM(32), _BM(22), _BM(10),	/* _PCPLT32, _PCPLT22, _PCPLT10 */
	_BM(10), _BM(11), -1,		/* _10, _11, _64 */
	_BM(10), _BM(22),		/* _OLO10, _HH22 */
	_BM(10), _BM(22),		/* _HM10, _LM22 */
	_BM(22), _BM(10), _BM(22),	/* _PC_HH22, _PC_HM10, _PC_LM22 */
	_BM(16), _BM(19),		/* _WDISP16, _WDISP19 */
	-1,				/* GLOB_JMP */
	_BM(7), _BM(5), _BM(6)		/* _7, _5, _6 */
	-1, -1,				/* DISP64, PLT64 */
	_BM(22), _BM(13),		/* HIX22, LOX10 */
	_BM(22), _BM(10), _BM(13),	/* H44, M44, L44 */
	-1, -1, _BM(16),		/* REGISTER, UA64, UA16 */
#undef _BM
};
#define RELOC_VALUE_BITMASK(t)	(reloc_target_bitmask[t])


int
_rtld_relocate_nonplt_object(obj, rela, dodebug)
	Obj_Entry *obj;
	const Elf_RelA *rela;
	bool dodebug;
{
	Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
	Elf_Word type;
	Elf_Addr value = 0, mask;
	const Elf_Sym *def = NULL;
	const Obj_Entry *defobj = NULL;

	type = ELF_R_TYPE(rela->r_info);
	if (type == R_TYPE(NONE))
		return (0);

	/* We do JMP_SLOTs in relocate_plt_object() below */
	if (type == R_TYPE(JMP_SLOT))
		return (0);

	/* COPY relocs are also handled elsewhere */
	if (type == R_TYPE(COPY))
		return (0);

	/*
	 * We use the fact that relocation types are an `enum'
	 * Note: R_SPARC_UA16 is currently numerically largest.
	 */
	if (type > R_TYPE(UA16))
		return (-1);

	value = rela->r_addend;

	/*
	 * Handle relative relocs here, because we might not
	 * be able to access globals yet.
	 */
	if (!dodebug && type == R_TYPE(RELATIVE)) {
		/* XXXX -- apparently we ignore the preexisting value */
		*where = (Elf_Addr)(obj->relocbase + value);
		return (0);
	}

	if (RELOC_RESOLVE_SYMBOL(type)) {

		/* Find the symbol */
		def = _rtld_find_symdef(_rtld_objlist, rela->r_info,
					NULL, obj, &defobj, false);
		if (def == NULL)
			return (-1);

		/* Add in the symbol's absolute address */
		value += (Elf_Addr)(defobj->relocbase + def->st_value);
	}

	if (RELOC_PC_RELATIVE(type)) {
		value -= (Elf_Addr)where;
	}

	if (RELOC_BASE_RELATIVE(type)) {
		/*
		 * Note that even though sparcs use `Elf_rela' exclusively
		 * we still need the implicit memory addend in relocations
		 * referring to GOT entries. Undoubtedly, someone f*cked
		 * this up in the distant past, and now we're stuck with
		 * it in the name of compatibility for all eternity..
		 *
		 * In any case, the implicit and explicit should be mutually
		 * exclusive. We provide a check for that here.
		 */
#ifdef DIAGNOSTIC
		if (value != 0 && *where != 0) {
			xprintf("BASE_REL(%s): where=%p, *where 0x%lx, "
				"addend=0x%lx, base %p\n",
				obj->path, where, *where,
				rela->r_addend, obj->relocbase);
		}
#endif
		/* XXXX -- apparently we ignore the preexisting value */
		value += (Elf_Addr)(obj->relocbase);
	}

	mask = RELOC_VALUE_BITMASK(type);
	value >>= RELOC_VALUE_RIGHTSHIFT(type);
	value &= mask;

	if (RELOC_UNALIGNED(type)) {
		/* Handle unaligned relocations. */
		Elf_Addr tmp = 0;
		char *ptr = (char *)where;
		int i, size = RELOC_TARGET_SIZE(type)/8;
		
		/* Read it in one byte at a time. */
		for (i=0; i<size; i++)
			tmp = (tmp << 8) | ptr[i];

		tmp &= ~mask;
		tmp |= value;

		/* Write it back out. */
		for (i=0; i<size; i++)
			ptr[i] = ((tmp >> (8*i)) & 0xff);
#ifdef RTLD_DEBUG_RELOC
		value = (Elf_Addr)tmp;
#endif

	} else if (RELOC_TARGET_SIZE(type) > 32) {
		*where &= ~mask;
		*where |= value;
#ifdef RTLD_DEBUG_RELOC
		value = (Elf_Addr)*where;
#endif
	} else {
		Elf32_Addr *where32 = (Elf32_Addr *)where;

		*where32 &= ~mask;
		*where32 |= value;
#ifdef RTLD_DEBUG_RELOC
		value = (Elf_Addr)*where32;
#endif
	}

#ifdef RTLD_DEBUG_RELOC
	if (RELOC_RESOLVE_SYMBOL(type)) {
		rdbg(dodebug, ("%s %s in %s --> %p %s", 
		    reloc_names[type],
		    defobj->strtab + def->st_name, obj->path,
		    (void *)value, defobj->path));
	}
	else {
		rdbg(dodebug, ("%s --> %p", reloc_names[type],
		    (void *)value));
	}
#endif
	return (0);
}

/*
 * Instruction templates:
 */
#define	BAA	0x10400000	/*	ba,a	%xcc, 0 */
#define	SETHI	0x03000000	/*	sethi	%hi(0), %g1 */
#define	JMP	0x81c06000	/*	jmpl	%g1+%lo(0), %g0 */
#define	NOP	0x01000000	/*	sethi	%hi(0), %g0 */
#define	OR	0x82806000	/*	or	%g1, 0, %g1 */
#define	XOR	0x82c06000	/*	xor	%g1, 0, %g1 */
#define	MOV71	0x8283a000	/*	or	%o7, 0, %g1 */
#define	MOV17	0x9c806000	/*	or	%g1, 0, %o7 */
#define	CALL	0x40000000	/*	call	0 */
#define	SLLX	0x8b407000	/*	sllx	%g1, 0, %g1 */
#define	SETHIG5	0x0b000000	/*	sethi	%hi(0), %g5 */
#define	ORG5	0x82804005	/*	or	%g1, %g5, %g1 */


/* %hi(v) with variable shift */
#define	HIVAL(v, s)	(((v) >> (s)) &  0x003fffff)
#define LOVAL(v)	((v) & 0x000003ff)

int
_rtld_relocate_plt_object(obj, rela, addrp, bind_now, dodebug)
	Obj_Entry *obj;
	const Elf_RelA *rela;
	caddr_t *addrp;
	bool bind_now;
	bool dodebug;
{
	const Elf_Sym *def;
	const Obj_Entry *defobj;
	Elf_Word *where = (Elf_Word *)((Elf_Addr)obj->relocbase + rela->r_offset);
	Elf_Addr value, offset;

	if (bind_now == 0 && obj->pltgot != NULL)
		return (0);

	/* Fully resolve procedure addresses now */

	assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));

	def = _rtld_find_symdef(_rtld_objlist, rela->r_info,
				NULL, obj, &defobj, true);
	if (def == NULL)
		return (-1);

	value = (Elf_Addr) (defobj->relocbase + def->st_value);
	rdbg(dodebug, ("bind now %d/fixup in %s --> old=%lx new=%lx", 
	    (int)bind_now, defobj->strtab + def->st_name,
	    (u_long)*where, (u_long)value));

	/*
	 * At the PLT entry pointed at by `where', we now construct
	 * a direct transfer to the now fully resolved function
	 * address.
	 *
	 * A PLT entry is supposed to start by looking like this:
	 *
	 *	sethi	%hi(. - .PLT0), %g1
	 *	ba,a	%xcc, .PLT1
	 *	nop
	 *	nop
	 *	nop
	 *	nop
	 *	nop
	 *	nop
	 *
	 * When we replace these entries we start from the second
	 * entry and do it in reverse order so the last thing we
	 * do is replace the branch.  That allows us to change this
	 * atomically.
	 *
	 * We now need to find out how far we need to jump.  We
	 * have a choice of several different relocation techniques
	 * which are increasingly expensive.
	 */

	offset = ((Elf_Addr)where) - value;
	if (rela->r_addend) {
		Elf_Addr *ptr = (Elf_Addr *)where;
		/*
		 * This entry is >32768.  Just replace the pointer.
		 */
		ptr[0] = value;

	} else if (offset <= (1L<<20) && offset >= -(1L<<20)) {
		/* 
		 * We're within 1MB -- we can use a direct branch insn.
		 *
		 * We can generate this pattern:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	ba,a	%xcc, addr
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[1] = BAA | ((offset >> 2) &0x3fffff);
		__asm __volatile("iflush %0+4" : : "r" (where));
	} else if (value >= 0 && value < (1L<<32)) {
		/* 
		 * We're withing 32-bits of address zero.
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%hi(addr), %g1
		 *	jmp	%g1+%lo(addr)
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[2] = JMP   | LOVAL(value);
		where[1] = SETHI | HIVAL(value, 10);
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	} else if (value <= 0 && value > -(1L<<32)) {
		/* 
		 * We're withing 32-bits of address -1.
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%hix(addr), %g1
		 *	xor	%g1, %lox(addr), %g1
		 *	jmp	%g1
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[3] = JMP;
		where[2] = XOR | ((~value) & 0x00001fff);
		where[1] = SETHI | HIVAL(~value, 10);
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	} else if (offset <= (1L<<32) && offset >= -((1L<<32) - 4)) {
		/* 
		 * We're withing 32-bits -- we can use a direct call insn 
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	mov	%o7, %g1
		 *	call	(.+offset)
		 *	 mov	%g1, %o7
		 *	nop
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[3] = MOV17;
		where[2] = CALL	  | ((offset >> 4) & 0x3fffffff);
		where[1] = MOV71;
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	} else if (offset >= 0 && offset < (1L<<44)) {
		/* 
		 * We're withing 44 bits.  We can generate this pattern:
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%h44(addr), %g1
		 *	or	%g1, %m44(addr), %g1
		 *	sllx	%g1, 12, %g1	
		 *	jmp	%g1+%l44(addr)	
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[4] = JMP   | LOVAL(offset);
		where[3] = SLLX  | 12;
		where[2] = OR    | (((offset) >> 12) & 0x00001fff);
		where[1] = SETHI | HIVAL(offset, 22);
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	} else if (offset < 0 && offset > -(1L<<44)) {
		/* 
		 * We're withing 44 bits.  We can generate this pattern:
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%h44(-addr), %g1
		 *	xor	%g1, %m44(-addr), %g1
		 *	sllx	%g1, 12, %g1	
		 *	jmp	%g1+%l44(addr)	
		 *	nop
		 *	nop
		 *	nop
		 *
		 */
		where[4] = JMP   | LOVAL(offset);
		where[3] = SLLX  | 12;
		where[2] = XOR   | (((~offset) >> 12) & 0x00001fff);
		where[1] = SETHI | HIVAL(~offset, 22);
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	} else {
		/* 
		 * We need to load all 64-bits
		 *
		 * The resulting code in the jump slot is:
		 *
		 *	sethi	%hi(. - .PLT0), %g1
		 *	sethi	%hh(addr), %g1
		 *	sethi	%lm(addr), %g5
		 *	or	%g1, %hm(addr), %g1
		 *	sllx	%g1, 32, %g1
		 *	or	%g1, %g5, %g1
		 *	jmp	%g1+%lo(addr)
		 *	nop
		 *
		 */
		where[6] = JMP     | LOVAL(value);
		where[5] = ORG5;
		where[4] = SLLX    | 12;
		where[3] = OR      | LOVAL((value) >> 32);
		where[2] = SETHIG5 | HIVAL(value, 10);
		where[1] = SETHI   | HIVAL(value, 42);
		__asm __volatile("iflush %0+20" : : "r" (where));
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+16" : : "r" (where));
		__asm __volatile("iflush %0+12" : : "r" (where));
		__asm __volatile("iflush %0+8" : : "r" (where));
		__asm __volatile("iflush %0+4" : : "r" (where));

	}

	if (addrp != NULL)
		*addrp = (caddr_t)value;

	return (0);
}

/*
 * Install rtld function call into this PLT slot.
 */
#define	SAVE		0x9de3bf50
#define	SETHI_l0	0x21000000
#define	SETHI_l1	0x23000000
#define	OR_l0_l0	0xa0142000
#define	SLLX_l0_32_l0	0xa12c3020
#define	OR_l0_l1_l0	0xa0140011
#define	JMPL_l0_o0	0x93c42000
#define	MOV_g1_o0	0x90100001

void _rtld_install_plt __P((Elf_Word *pltgot,	Elf_Addr proc));

void
_rtld_install_plt(pltgot, proc)
	Elf_Word *pltgot;
	Elf_Addr proc;
{
	pltgot[0] = SAVE;
	pltgot[1] = SETHI_l0  | HIVAL(proc, 42);
	pltgot[2] = SETHI_l1  | HIVAL(proc, 10);
	pltgot[3] = OR_l0_l0  | LOVAL((proc) >> 32);
	pltgot[4] = SLLX_l0_32_l0;
	pltgot[5] = OR_l0_l1_l0;
	pltgot[6] = JMPL_l0_o0 | LOVAL(proc);
	pltgot[7] = MOV_g1_o0;
}

long _rtld_bind_start_0_stub __P((long x, long y));
long 
_rtld_bind_start_0_stub(x, y)
	long x, y;
{
	long i;
	long n;

	i = x - y + 1048596;
	n = 32768 + (i/5120)*160 + (i%5120)/24;

	return (n);
}

@


1.3.2.3
log
@Pull up revision 1.5 (requested by kleink):
  Rename ElfNN_RelA to ElfNN_Rela, which is what SVR4 ABIs and the
  rest of the world uses.  Fixes PR#12274.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.3.2.2 2001/05/01 12:07:23 he Exp $	*/
d191 1
a191 1
	const Elf_Rela *rela;
d349 1
a349 1
	const Elf_Rela *rela;
@


1.3.2.4
log
@Pull up revision 1.4 (requested by skrll):
  Add init/fini section support in crtbegin and crtend, and introduce
  support for DWARF2 exception handling.  Fixes PR#12865, PR#13488,
  PR#13489, and PR#13491.  Also fix ld.elf_so to deal appropriately.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.3.2.3 2001/12/09 17:23:30 he Exp $	*/
d591 1
a591 1
#define	JMPL_l0_o1	0x93c42000
d607 1
a607 1
	pltgot[6] = JMPL_l0_o1 | LOVAL(proc);
@


1.2
log
@Fix some issues with SPARC V9 ELF binaries.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.1 2000/07/13 23:14:18 eeh Exp $	*/
d195 2
a196 1
	Elf_Word type, value = 0, mask;
d240 1
a240 1
		value += (Elf_Word)(defobj->relocbase + def->st_value);
d244 1
a244 1
		value -= (Elf_Word)where;
d267 1
a267 1
		value += (Elf_Word)(obj->relocbase);
d276 1
a276 1
		Elf_Word tmp = 0;
d291 1
a291 1
		value = (Elf_Word)tmp;
d298 1
a298 1
		value = (Elf_Word)*where;
d306 1
a306 1
		value = (Elf_Word)*where32;
d356 1
a356 1
	Elf32_Word *where = (Elf32_Word *)((Elf_Addr)obj->pltgot + rela->r_offset);
d594 1
a594 1
void _rtld_install_plt __P((Elf32_Word *pltgot,	Elf_Addr proc));
d598 1
a598 1
	Elf32_Word *pltgot;
@


1.1
log
@Added support for the SPARC v9 ABI.
@
text
@d1 1
a1 1
/*	$NetBSD: mdreloc.c,v 1.9 1999/11/07 08:08:15 mycroft Exp $	*/
d70 1
d97 1
a97 1
	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* UA_32 */
d129 2
a130 2
	_RF_S|_RF_A|		_RF_SZ(64) | _RF_RS(0),		/* UA64 */
	_RF_S|_RF_A|		_RF_SZ(16) | _RF_RS(0),		/* UA16 */
d152 2
d195 1
a195 1
	Elf_Word type, value, mask;
d225 2
a226 1
		*where += (Elf_Addr)(obj->relocbase + value);
a256 1
#define DIAGNOSTIC
d265 2
a266 1
		value += (Elf_Word)(obj->relocbase + *where);
d273 21
a293 2
	/* We ignore alignment restrictions here */
	if (RELOC_TARGET_SIZE(type) > 32) {
d355 1
a355 1
	Elf32_Word *where = (Elf32_Word *) (obj->relocbase + rela->r_offset);
d371 1
a371 1
	rdbg(dodebug, ("bind now %d/fixup in %s --> old=%p new=%p", 
d373 1
a373 1
	    (void *)*where, (void *)value));
d609 15
@
