This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [gold commit] Aligning segments in gold
- From: Cary Coutant <ccoutant at google dot com>
- To: Binutils <binutils at sourceware dot org>, Alan Modra <amodra at gmail dot com>
- Date: Fri, 23 Jan 2015 18:17:02 -0800
- Subject: Re: [gold commit] Aligning segments in gold
- Authentication-results: sourceware.org; auth=none
- References: <CAHACq4rL5h6B660cpxdisgXg3dkmRkKnycTyftRn7Uq--YjbxA at mail dot gmail dot com> <20150114072650 dot GN23768 at bubble dot grove dot modra dot org> <CAHACq4rDhT34ouquSGAP00i+4Q1WYnvBJF-6kj9YGFp1DJhJKw at mail dot gmail dot com> <20150114233357 dot GO23768 at bubble dot grove dot modra dot org>
>> > This appears to cause the following failure on powerpc64.
>> >
>> > `echo g++ -Bgcctestdir/ -m64 -W -Wall -Werror -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fmerge-constants -g -O -fno-inline -fno-use-linker-plugin -o relro_test.so | sed -e 's/-Wp,-D_FORTIFY_SOURCE=[0-9][0-9]*//'` -shared -Wl,-z,relro relro_test_pic.o
>> > gcctestdir/collect-ld: internal error in set_offset, at /src/binutils-gdb/gold/output.cc:4686
>>
>> Unfortunately, with the ppc64 toolchain I have, I can't reproduce this
>> error. Can you send me your copy of relro_test_pic.o? (Since I don't
>> have a native machine to test on, I had to cross-compile and link with
>> an x86-hosted gold. So that may have changed things.)
>
> Attached. Reproduces with native and x86_64 hosted gold.
> ./ld-new --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -shared -m elf64ppc -o relro_test.so -z relro relro_test_pic.o
The patch below appears to fix it (the first chunk is the actual fix;
the second chunk is just cleanup). Could you test it out before I
commit? I have a similar failure on x86 native that I'll also use to
verify (but it's not easy to run that repro as it was to run yours!).
Basically, we were calculating the size of the relro segment by
temporarily assigning addresses and offsets to each relro section,
based on the current offset. Previously, we were always aligning the
current offset before each segment to a page boundary, but now we're
not, and the temporary assignment was based on what is now a
potentially-unaligned starting offset. Instead, I start the temporary
assignment at offset 0.
-cary
2015-01-23 Cary Coutant <ccoutant@google.com>
gold/
* output.cc (Output_segment::set_section_addresses): Fix calculation
of size of relro segment.
diff --git a/gold/output.cc b/gold/output.cc
index 9a51131..e9dd522 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -4311,8 +4311,8 @@ Output_segment::set_section_addresses(const
Target* target,
else
{
// FIXME: This could be faster.
- (*p)->set_address_and_file_offset(addr + relro_size,
- off + relro_size);
+ (*p)->set_address_and_file_offset(relro_size,
+ relro_size);
relro_size += (*p)->data_size();
(*p)->reset_address_and_file_offset();
}
@@ -4332,11 +4332,12 @@ Output_segment::set_section_addresses(const
Target* target,
// Align to offset N such that (N + RELRO_SIZE) % PAGE_ALIGN == 0.
uint64_t desired_align = page_align - (aligned_size % page_align);
- if (desired_align < *poff % page_align)
- *poff += page_align - *poff % page_align;
- *poff += desired_align - *poff % page_align;
- addr += *poff - orig_off;
- orig_off = *poff;
+ if (desired_align < off % page_align)
+ off += page_align;
+ off += desired_align - off % page_align;
+ addr += off - orig_off;
+ orig_off = off;
+ *poff = off;
}
if (!reset && this->are_addresses_set_)