git: e6c769620316 - main - rtld: Fix i386/amd64 TP offset when p_vaddr % p_align != 0

Konstantin Belousov kib at FreeBSD.org
Mon Aug 16 10:56:15 UTC 2021


The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=e6c76962031625d51fe4225ecfa15c85155eb13a

commit e6c76962031625d51fe4225ecfa15c85155eb13a
Author:     Fangrui Song <i at maskray.me>
AuthorDate: 2021-08-14 16:56:58 +0000
Commit:     Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-08-16 10:55:34 +0000

    rtld: Fix i386/amd64 TP offset when p_vaddr % p_align != 0
    
    For a Variant II architecture, the TP offset of a TLS symbol is st_value -
    tlsoffset + r_addend. tlsoffset is computed by either calculate_tls_offset
    or calculate_first_tls_offset.
    
    The return value of calculate_first_tls_offset is the smallest integer
    satisfying res >= size and (-res) % p_align = p_vaddr % p_align
    (= p_offset % p_align).  (The formula is a bit contrived. The basic idea
    is to subtract the minimum integer from size + align - 1 so that the result
    ihas the expected remainder.)
    
    Reviewed by:    kib
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D31538
    Differential revision:  https://reviews.freebsd.org/D31541
---
 libexec/rtld-elf/amd64/reloc.c | 27 ++++++++++++---------------
 libexec/rtld-elf/i386/reloc.c  | 27 ++++++++++++---------------
 2 files changed, 24 insertions(+), 30 deletions(-)

diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c
index 689b0d8635d4..508ae04a7448 100644
--- a/libexec/rtld-elf/amd64/reloc.c
+++ b/libexec/rtld-elf/amd64/reloc.c
@@ -548,29 +548,26 @@ __tls_get_addr(tls_index *ti)
 }
 
 size_t
-calculate_first_tls_offset(size_t size, size_t align, size_t offset)
+calculate_tls_offset(size_t prev_offset, size_t prev_size __unused,
+    size_t size, size_t align, size_t offset)
 {
 	size_t res;
 
-	res = roundup(size, align);
-	offset &= align - 1;
-	if (offset != 0)
-		res += align - offset;
-	return (res);
+        /*
+	 * res is the smallest integer satisfying res - prev_offset >= size
+         * and (-res) % p_align = p_vaddr % p_align (= p_offset % p_align).
+	 */
+        res = prev_offset + size + align - 1;
+        res -= (res + offset) & (align - 1);
+        return (res);
 }
 
 size_t
-calculate_tls_offset(size_t prev_offset, size_t prev_size __unused, size_t size,
-    size_t align, size_t offset)
+calculate_first_tls_offset(size_t size, size_t align, size_t offset)
 {
-	size_t res;
-
-	res = roundup(prev_offset + size, align);
-	offset &= align - 1;
-	if (offset != 0)
-		res += align - offset;
-	return (res);
+	return (calculate_tls_offset(0, 0, size, align, offset));
 }
+
 size_t
 calculate_tls_end(size_t off, size_t size __unused)
 {
diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c
index cab163b35e6a..69da93347bbb 100644
--- a/libexec/rtld-elf/i386/reloc.c
+++ b/libexec/rtld-elf/i386/reloc.c
@@ -539,29 +539,26 @@ __tls_get_addr(tls_index *ti)
 }
 
 size_t
-calculate_first_tls_offset(size_t size, size_t align, size_t offset)
+calculate_tls_offset(size_t prev_offset, size_t prev_size __unused,
+    size_t size, size_t align, size_t offset)
 {
 	size_t res;
 
-	res = roundup(size, align);
-	offset &= align - 1;
-	if (offset != 0)
-		res += align - offset;
-	return (res);
+        /*
+	 * res is the smallest integer satisfying res - prev_offset >= size
+         * and (-res) % p_align = p_vaddr % p_align (= p_offset % p_align).
+	 */
+        res = prev_offset + size + align - 1;
+        res -= (res + offset) & (align - 1);
+        return (res);
 }
 
 size_t
-calculate_tls_offset(size_t prev_offset, size_t prev_size __unused, size_t size,
-    size_t align, size_t offset)
+calculate_first_tls_offset(size_t size, size_t align, size_t offset)
 {
-	size_t res;
-
-	res = roundup(prev_offset + size, align);
-	offset &= align - 1;
-	if (offset != 0)
-		res += align - offset;
-	return (res);
+	return (calculate_tls_offset(0, 0, size, align, offset));
 }
+
 size_t
 calculate_tls_end(size_t off, size_t size __unused)
 {


More information about the dev-commits-src-all mailing list