This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[RFC] Aligning segments in gold
- From: Cary Coutant <ccoutant at google dot com>
- To: Ian Lance Taylor <iant at google dot com>
- Cc: Binutils <binutils at sourceware dot org>
- Date: Fri, 9 Jan 2015 14:29:05 -0800
- Subject: [RFC] Aligning segments in gold
- Authentication-results: sourceware.org; auth=none
Ian,
In Layout::set_segment_offsets, we have this code:
// Skip the address forward one page, maintaining the same
// position within the page. This lets us store both segments
// overlapping on a single page in the file, but the loader will
// put them on different pages in memory. We will revisit this
// decision once we know the size of the segment.
addr = align_address(addr, (*p)->maximum_alignment());
aligned_addr = addr;
if (load_seg == *p)
{
// ...
}
else
{
if ((addr & (abi_pagesize - 1)) != 0)
addr = addr + abi_pagesize;
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
}
Usually, this works fine -- we'll set addr = addr + abi_pagesize, then
adjust off so that we share a page in the file. But what happens when
(*p)->maximum_alignment() returns a large value like 4096? We end up
aligning addr first to a page boundary, and that's all. If -z relro
adjustment results in more padding such that we *could* have
overlapped the segments in the file, we lose the opportunity and end
up wasting a page. If we subsequently run the output through strip,
strip will "fix" that for us, the p_offset fields won't match, and GDB
will complain that the unstripped binary doesn't match the core file.
I'm thinking we don't need to align to (*p)->maximum_alignment() at
all here, unless it's larger than abi_pagesize. Each output section in
the segment will be aligned appropriately without that, and we don't
need the segment's starting address to match that alignment, since the
loader always preserves the offset modulo page size when relocating
segments. Indeed, with relro adjustment, the starting address of the
segment rarely matches the alignment of its most strictly-aligned
section.
What do you think?
-cary
diff --git a/gold/layout.cc b/gold/layout.cc
index acc03b2..bcdaac8 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -3524,7 +3524,9 @@ Layout::set_segment_offsets(const Target*
target, Output_segment* load_seg,
// put them on different pages in memory. We will revisit this
// decision once we know the size of the segment.
- addr = align_address(addr, (*p)->maximum_alignment());
+ uint64_t max_align = (*p)->maximum_alignment();
+ if (max_align > abi_pagesize)
+ addr = align_address(addr, max_align);
aligned_addr = addr;
if (load_seg == *p)