mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-27 22:10:32 +00:00
Make sure the start and size of the TLS segment are aligned.
This commit is contained in:
parent
49a834f99f
commit
96a2b4e4bf
@ -1535,8 +1535,8 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
|
||||
}
|
||||
|
||||
unsigned int shndx_hold = *pshndx;
|
||||
uint64_t new_addr = (*p)->set_section_addresses(false, addr, &off,
|
||||
pshndx);
|
||||
uint64_t new_addr = (*p)->set_section_addresses(this, false, addr,
|
||||
&off, pshndx);
|
||||
|
||||
// Now that we know the size of this segment, we may be able
|
||||
// to save a page in memory, at the cost of wasting some
|
||||
@ -1561,8 +1561,8 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
|
||||
addr = align_address(aligned_addr, common_pagesize);
|
||||
addr = align_address(addr, (*p)->maximum_alignment());
|
||||
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
|
||||
new_addr = (*p)->set_section_addresses(true, addr, &off,
|
||||
pshndx);
|
||||
new_addr = (*p)->set_section_addresses(this, true, addr,
|
||||
&off, pshndx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2483,7 +2483,8 @@ Output_segment::dynamic_reloc_count_list(const Output_data_list* pdl) const
|
||||
// *POFF and *PSHNDX.
|
||||
|
||||
uint64_t
|
||||
Output_segment::set_section_addresses(bool reset, uint64_t addr, off_t* poff,
|
||||
Output_segment::set_section_addresses(const Layout* layout, bool reset,
|
||||
uint64_t addr, off_t* poff,
|
||||
unsigned int* pshndx)
|
||||
{
|
||||
gold_assert(this->type_ == elfcpp::PT_LOAD);
|
||||
@ -2500,17 +2501,31 @@ Output_segment::set_section_addresses(bool reset, uint64_t addr, off_t* poff,
|
||||
this->are_addresses_set_ = true;
|
||||
}
|
||||
|
||||
bool in_tls = false;
|
||||
|
||||
off_t orig_off = *poff;
|
||||
this->offset_ = orig_off;
|
||||
|
||||
addr = this->set_section_list_addresses(reset, &this->output_data_,
|
||||
addr, poff, pshndx);
|
||||
addr = this->set_section_list_addresses(layout, reset, &this->output_data_,
|
||||
addr, poff, pshndx, &in_tls);
|
||||
this->filesz_ = *poff - orig_off;
|
||||
|
||||
off_t off = *poff;
|
||||
|
||||
uint64_t ret = this->set_section_list_addresses(reset, &this->output_bss_,
|
||||
addr, poff, pshndx);
|
||||
uint64_t ret = this->set_section_list_addresses(layout, reset,
|
||||
&this->output_bss_,
|
||||
addr, poff, pshndx,
|
||||
&in_tls);
|
||||
|
||||
// If the last section was a TLS section, align upward to the
|
||||
// alignment of the TLS segment, so that the overall size of the TLS
|
||||
// segment is aligned.
|
||||
if (in_tls)
|
||||
{
|
||||
uint64_t segment_align = layout->tls_segment()->maximum_alignment();
|
||||
*poff = align_address(*poff, segment_align);
|
||||
}
|
||||
|
||||
this->memsz_ = *poff - orig_off;
|
||||
|
||||
// Ignore the file offset adjustments made by the BSS Output_data
|
||||
@ -2524,9 +2539,11 @@ Output_segment::set_section_addresses(bool reset, uint64_t addr, off_t* poff,
|
||||
// structures.
|
||||
|
||||
uint64_t
|
||||
Output_segment::set_section_list_addresses(bool reset, Output_data_list* pdl,
|
||||
Output_segment::set_section_list_addresses(const Layout* layout, bool reset,
|
||||
Output_data_list* pdl,
|
||||
uint64_t addr, off_t* poff,
|
||||
unsigned int* pshndx)
|
||||
unsigned int* pshndx,
|
||||
bool* in_tls)
|
||||
{
|
||||
off_t startoff = *poff;
|
||||
|
||||
@ -2542,7 +2559,42 @@ Output_segment::set_section_list_addresses(bool reset, Output_data_list* pdl,
|
||||
// already have an address.
|
||||
if (!(*p)->is_address_valid())
|
||||
{
|
||||
off = align_address(off, (*p)->addralign());
|
||||
uint64_t align = (*p)->addralign();
|
||||
|
||||
if ((*p)->is_section_flag_set(elfcpp::SHF_TLS))
|
||||
{
|
||||
// Give the first TLS section the alignment of the
|
||||
// entire TLS segment. Otherwise the TLS segment as a
|
||||
// whole may be misaligned.
|
||||
if (!*in_tls)
|
||||
{
|
||||
Output_segment* tls_segment = layout->tls_segment();
|
||||
gold_assert(tls_segment != NULL);
|
||||
uint64_t segment_align = tls_segment->maximum_alignment();
|
||||
gold_assert(segment_align >= align);
|
||||
align = segment_align;
|
||||
|
||||
*in_tls = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this is the first section after the TLS segment,
|
||||
// align it to at least the alignment of the TLS
|
||||
// segment, so that the size of the overall TLS segment
|
||||
// is aligned.
|
||||
if (*in_tls)
|
||||
{
|
||||
uint64_t segment_align =
|
||||
layout->tls_segment()->maximum_alignment();
|
||||
if (segment_align > align)
|
||||
align = segment_align;
|
||||
|
||||
*in_tls = false;
|
||||
}
|
||||
}
|
||||
|
||||
off = align_address(off, align);
|
||||
(*p)->set_address_and_file_offset(addr + (off - startoff), off);
|
||||
}
|
||||
else
|
||||
@ -2555,11 +2607,10 @@ Output_segment::set_section_list_addresses(bool reset, Output_data_list* pdl,
|
||||
(*p)->finalize_data_size();
|
||||
}
|
||||
|
||||
// Unless this is a PT_TLS segment, we want to ignore the size
|
||||
// of a SHF_TLS/SHT_NOBITS section. Such a section does not
|
||||
// affect the size of a PT_LOAD segment.
|
||||
if (this->type_ == elfcpp::PT_TLS
|
||||
|| !(*p)->is_section_flag_set(elfcpp::SHF_TLS)
|
||||
// We want to ignore the size of a SHF_TLS or SHT_NOBITS
|
||||
// section. Such a section does not affect the size of a
|
||||
// PT_LOAD segment.
|
||||
if (!(*p)->is_section_flag_set(elfcpp::SHF_TLS)
|
||||
|| !(*p)->is_section_type(elfcpp::SHT_NOBITS))
|
||||
off += (*p)->data_size();
|
||||
|
||||
@ -2626,6 +2677,16 @@ Output_segment::set_offset()
|
||||
this->memsz_ = (last->address()
|
||||
+ last->data_size()
|
||||
- this->vaddr_);
|
||||
|
||||
// If this is a TLS segment, align the memory size. The code in
|
||||
// set_section_list ensures that the section after the TLS segment
|
||||
// is aligned to give us room.
|
||||
if (this->type_ == elfcpp::PT_TLS)
|
||||
{
|
||||
uint64_t segment_align = this->maximum_alignment();
|
||||
gold_assert(this->vaddr_ == align_address(this->vaddr_, segment_align));
|
||||
this->memsz_ = align_address(this->memsz_, segment_align);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the TLS offsets of the sections in the PT_TLS segment.
|
||||
|
@ -2582,7 +2582,7 @@ class Output_segment
|
||||
// address of the immediately following segment. Update *POFF and
|
||||
// *PSHNDX. This should only be called for a PT_LOAD segment.
|
||||
uint64_t
|
||||
set_section_addresses(bool reset, uint64_t addr, off_t* poff,
|
||||
set_section_addresses(const Layout*, bool reset, uint64_t addr, off_t* poff,
|
||||
unsigned int* pshndx);
|
||||
|
||||
// Set the minimum alignment of this segment. This may be adjusted
|
||||
@ -2638,8 +2638,9 @@ class Output_segment
|
||||
|
||||
// Set the section addresses in an Output_data_list.
|
||||
uint64_t
|
||||
set_section_list_addresses(bool reset, Output_data_list*, uint64_t addr,
|
||||
off_t* poff, unsigned int* pshndx);
|
||||
set_section_list_addresses(const Layout*, bool reset, Output_data_list*,
|
||||
uint64_t addr, off_t* poff, unsigned int* pshndx,
|
||||
bool* in_tls);
|
||||
|
||||
// Return the number of Output_sections in an Output_data_list.
|
||||
unsigned int
|
||||
|
@ -60,6 +60,13 @@
|
||||
|
||||
__thread int v1;
|
||||
static __thread int v2;
|
||||
|
||||
// We don't use these pointers, but putting them in tests alignment on
|
||||
// a 64-bit target.
|
||||
__thread char* p1;
|
||||
char dummy;
|
||||
__thread char* p2 = &dummy;
|
||||
|
||||
__thread int v3 = 3;
|
||||
static __thread int v4 = 4;
|
||||
__thread int v5;
|
||||
|
Loading…
Reference in New Issue
Block a user