Page MenuHomePhabricator

Make .rodata* and .eh_frame* the last of all PROGBITS sections.
Needs ReviewPublic

Authored by pohlen on Feb 10 2020, 9:08 AM.

Details

Summary

Some software vendors (such as NVidia) ship proprietary program code for specialized hardware (e.g. GPUs) in vendor-specific PROGBITS sections (e.g. .nv_fatbin). Before this change, these section may have been placed between .rodata and .text, which leads to relocation overflows even when the actual program code is small because these vendor-specific sections can be quite big (e.g. .nv_fatbin can be >1GiB when including support for various GPU architectures).

Diff Detail

Event Timeline

pohlen created this revision.Feb 10 2020, 9:08 AM
MaskRay added a subscriber: tra.EditedFeb 10 2020, 12:28 PM

+@tra because of D47396

What types of relocations are from/to .nv_fatbin?

tra added a comment.Feb 10 2020, 12:40 PM

+@tra because of D47396

What types of relocations are from/to .nv_fatbin?

Normally the only things that refer to the stuff in .nv_* are static data structures in .rodata, so placing .nv_fatbin before that is the right thing to do, as long as it does not get in a way of something else.

MaskRay added a comment.EditedFeb 10 2020, 1:32 PM

does an output section have limited-range relocations referring to or from it? If so, move it to the end of the segment

What I am a bit concerned is that relocations in input sections can cause layout changes (a little surprise). The heuristic of output section sizes is similar.

In D74339#1867939, @tra wrote:

+@tra because of D47396

What types of relocations are from/to .nv_fatbin?

Normally the only things that refer to the stuff in .nv_* are static data structures in .rodata, so placing .nv_fatbin before that is the right thing to do, as long as it does not get in a way of something else.

A less ad-hoc rule is to implement INSERT BEFORE for orphan sections. It currently only works for a linker script (see test/ELF/linkerscript/insert-before.test). I prefer general INSERT BEFORE and INSERT AFTER because they make the fixed internal linker script logic a bit more flexible.

In GNU ld, INSERT BEFORE is not considered an external linker script. lld currently has script->hasSectionCommands = true; => this should be fixed. INSERT BEFORE provide a quick way for disturbing the section layout. They can be used as a workaround for other relocation overflow problems.

It is difficult to get a working executable with clang -fuse-ld=lld a.c -Wl,-T,a.x, because an application-like linker script needs to create PT_LOAD segment boundaries by explicitly mentioning the first section for each PT_LOAD segment. If such an alignment is omitted => sh_addr of the first section of one PT_LOAD is not correct -> the created PT_LOAD may have overlapping p_vaddr ranges (after modulo maxpagesize at ).

A skeleton linker script which should work with both -no-pie (image base (0x400000) is required and -pie (0x400000 is not required, but it does not hurt):

SECTIONS {
  . = SIZEOF_HEADERS + 0x400000;
  .rodata : { *(.rodata*) }
  .text : { *(.text*) }
  . = ALIGN(CONSTANT(MAXPAGESIZE)) + . % CONSTANT(MAXPAGESIZE);
  .fini_array : { *(.fini_array*) }
  . = ALIGN(CONSTANT(MAXPAGESIZE)) + . % CONSTANT(MAXPAGESIZE);
  .data : { *(.data*) }
}

Created D74375 . I think INSERT [AFTER|BEFORE] is a great solution to this kind of problems..

psmith added a subscriber: psmith.Feb 11 2020, 4:42 AM

Created D74375 . I think INSERT [AFTER|BEFORE] is a great solution to this kind of problems..

I agree with MaskRay that if section layout of non-standard custom sections is important then a linker script, or linker script fragment is a cleaner way to accomplish it.