This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] Aligning segments in gold


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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]