Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 4 Jul 2014 17:38:50 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        "Ivan A. Kosarev" <ivan@ivan-labs.com>
Cc:        toolchain@freebsd.org, freebsd-current@freebsd.org
Subject:   Re: Intercepting calls in PIC mode
Message-ID:  <20140704143850.GH93733@kib.kiev.ua>
In-Reply-To: <53B69A43.3000100@ivan-labs.com>
References:  <53B69A43.3000100@ivan-labs.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--JBmVoN0GeLJFe550
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Fri, Jul 04, 2014 at 04:12:51PM +0400, Ivan A. Kosarev wrote:
> Hello,
>=20
> Consider the following:
>=20
> ---
> #include <stdio.h>
> #include <string.h>
>=20
> extern "C" void* memset(void *block, int c, size_t size)
>      __attribute__((weak, alias("__int_memset"), visibility("default")));
>=20
> extern "C" __attribute__((visibility("default")))
> void* __int_memset(void *block, int c, size_t size) {
>      puts("Hello");
>      return NULL;
> }
>=20
> int main()
> {
>      void *(*F)(void *b, int c, size_t len) =3D memset;
>      char a[5];
>      memset(a, 0, sizeof(a));
>      F(a, 0, sizeof(a));
>      return 0;
> }
> ---
>=20
> It intercepts the memset() calls without issue on both x86-64 FreeBSD=20
> 9.2 and Linux. However, with the -fPIC option specified in the cc's=20
> command line, only the first (direct) call work on FreeBSD, but not the=
=20
> second (indirect) one. Note is that on Linux both the calls are=20
> intercepted--no matter whether the -fPIC option is specified or not.

Your example is rather convoluted, I will try to explain below why.

First, I am sure that C99 does not allow to override the semantic of the
standard-defined functions.  That said, a call to memset(3) can be
inlined by a compiler, so there could be nothing to intercept.

Second, FreeBSD implementation of the weak ELF symbols is non-compliant.
The dynamic linker prioritizes non-weak symbols over the weak. This at
least explains why your code snippet does not segfaults: the memset(3)
=66rom libc is not interposed by your memset() implementation, so libc can
at least initialize itself.  If you remove weak attribute from the memset(),
debug version of libc fails with assertions in jemalloc, while normal
build just segfaults.

That said, there are also differences in the static linker behaviour.
Clang generates the following code to obtain the address of the memset(3)
function:
		movq	memset@GOTPCREL(%rip), %rsi

The in-tree ld from binutils 2.17.redhat generates the
R_X86_64_GLOB_DAT relocation to fill the GOT entry for the memset
symbol.  Processor of the GLOB_DAT in the rtld-elf always starts
the lookup of the requested symbol in the object next from main.
For your code, this means libc is searched for memset to fill the
slot, and you get a libc symbol.

The ld from the stock build of binutils 2.24, on the other hand, does not
generate a relocation at all, it resolves memset internally from the same
object file and fills the offset directly into instruction.  I.e., when
the program is linked with new ld, it works as you intend.  This is
probably the reason why it worked for you on Linux.

I am not sure what conclusion could be made from the story I just told you.
Might be, 'do not try to interpose std C functions' and 'put interposers
into the LD_PRELOADed objects' ?

--JBmVoN0GeLJFe550
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQIcBAEBAgAGBQJTtrx6AAoJEJDCuSvBvK1B42YP/21lu2qUek1o0EsT/ePohCSX
f32abyLwhhZkG1RGlpoeHvOtGBsJhZ2xSHFVgLd+zMbvJ2Yx4H9U+7+zcybSGTB3
J9g2FmkOH4/SXN+SkSijt/T8gVz+JKdcb8nB/EhPcZBxVBrvv7VSs3e62yFLC7aJ
bil4OkAvEqQvi0w7Qw0Jj2IDjSgqIQkBg5l+rBeayCS695oSxsgIFXz0+Nz8jhqY
U0VizVeLwYuUbczqsvItoyMQM/JTKyuqEb/yGK/iMR0bNoR85wyp4nM+bawYmjkr
abF2fGmoshDafbAemDpWc2KCGds76O+RBtpGTY5nIKt/BmgRw8gBHlCzkA5DRjjU
uEAG5c4M23IST0G1u44feuk6k+6fcxmNgPX+H/k6iTA01mNlfMI2jIaoC6RvIUKL
MHtQijVZXtnrlgDkgVaE/8lYz+SeK7q38GmD72f/s7LIBh/UVSo9NCzKe1MAEGe2
+Nqhz34Hby5L+bsYKVSS4O8EeP04qH9Y21Pa7YXWzAA+ynsGcShBl/H//L/gX55g
v2JTRAAPjkJ5MB8ypiOig0KxE1fB33GNmK193eYqWOCK50wL6dYW9zpaVf2U1lRP
WFM2aUBK6iJQqxSE81NhzZpIlHVWlvJWoA2oG9Eyl8fZgsyocOjrKynyz4ZBiIiA
kAmd9HTGfvPuxzjo8ixp
=GF6d
-----END PGP SIGNATURE-----

--JBmVoN0GeLJFe550--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140704143850.GH93733>