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
This commit is contained in:
parent
cc1345056b
commit
e6c7696203
@ -548,29 +548,26 @@ __tls_get_addr(tls_index *ti)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
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;
|
size_t res;
|
||||||
|
|
||||||
res = roundup(size, align);
|
/*
|
||||||
offset &= align - 1;
|
* res is the smallest integer satisfying res - prev_offset >= size
|
||||||
if (offset != 0)
|
* and (-res) % p_align = p_vaddr % p_align (= p_offset % p_align).
|
||||||
res += align - offset;
|
*/
|
||||||
return (res);
|
res = prev_offset + size + align - 1;
|
||||||
|
res -= (res + offset) & (align - 1);
|
||||||
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
calculate_tls_offset(size_t prev_offset, size_t prev_size __unused, size_t size,
|
calculate_first_tls_offset(size_t size, size_t align, size_t offset)
|
||||||
size_t align, size_t offset)
|
|
||||||
{
|
{
|
||||||
size_t res;
|
return (calculate_tls_offset(0, 0, size, align, offset));
|
||||||
|
|
||||||
res = roundup(prev_offset + size, align);
|
|
||||||
offset &= align - 1;
|
|
||||||
if (offset != 0)
|
|
||||||
res += align - offset;
|
|
||||||
return (res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
calculate_tls_end(size_t off, size_t size __unused)
|
calculate_tls_end(size_t off, size_t size __unused)
|
||||||
{
|
{
|
||||||
|
@ -539,29 +539,26 @@ __tls_get_addr(tls_index *ti)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
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;
|
size_t res;
|
||||||
|
|
||||||
res = roundup(size, align);
|
/*
|
||||||
offset &= align - 1;
|
* res is the smallest integer satisfying res - prev_offset >= size
|
||||||
if (offset != 0)
|
* and (-res) % p_align = p_vaddr % p_align (= p_offset % p_align).
|
||||||
res += align - offset;
|
*/
|
||||||
return (res);
|
res = prev_offset + size + align - 1;
|
||||||
|
res -= (res + offset) & (align - 1);
|
||||||
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
calculate_tls_offset(size_t prev_offset, size_t prev_size __unused, size_t size,
|
calculate_first_tls_offset(size_t size, size_t align, size_t offset)
|
||||||
size_t align, size_t offset)
|
|
||||||
{
|
{
|
||||||
size_t res;
|
return (calculate_tls_offset(0, 0, size, align, offset));
|
||||||
|
|
||||||
res = roundup(prev_offset + size, align);
|
|
||||||
offset &= align - 1;
|
|
||||||
if (offset != 0)
|
|
||||||
res += align - offset;
|
|
||||||
return (res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
calculate_tls_end(size_t off, size_t size __unused)
|
calculate_tls_end(size_t off, size_t size __unused)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user