-
Notifications
You must be signed in to change notification settings - Fork 43
Support z separate/no-separate code #707
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -178,6 +178,25 @@ bool GNULDBackend::createProgramHdrs() { | |
|
|
||
| reset_state(); | ||
|
|
||
| auto SeparateKind = config().options().getSeparateSegmentKind(); | ||
| bool ShouldSeparate = | ||
| !linkerScriptHasSectionsCommand && | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems that the |
||
| (SeparateKind != GeneralOptions::SeparateSegmentKind::None); | ||
|
|
||
| auto ShouldPageAlignSegment = [&](bool IsExec) { | ||
| if (config().options().alignSegmentsToPage()) | ||
| return true; | ||
| if (!ShouldSeparate) | ||
| return false; | ||
| if (!prevOut) | ||
| return false; | ||
| auto PrevSegIt = _segmentsForSection.find(prevOut); | ||
| if (PrevSegIt == _segmentsForSection.end() || PrevSegIt->second.empty()) | ||
| return false; | ||
| bool PrevExec = (PrevSegIt->second.front()->flag() & llvm::ELF::PF_X); | ||
| return PrevExec != IsExec; | ||
| }; | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we rename this to something better since the lambda does nore than aligning segments to a page ? Why does aligning segments to a page not work with -z seperate-code ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If it does anything more than determine whether or not segments should be page aligned then I did something wrong. Taking another look, I am not seeing that it does anything other than that. What am I missing? What name do you suggest?
I am not sure if I understand your question. It does "work". Starting code segments at page aligned offsets ensures that they are not co-resident on the same page as other segments. That is the point of this lambda function: when transitioning to/from a code segment to another kind of segment, with
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The lambda checks for the variety of things
Should this be called DoPageAlignment or NeedSeperateSegmentOrPageAlign ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Because it is relevant to determine if we It checks if we should page align segments based on:
I don't see how these are better names. They sound like (worse) synonyms to me. |
||
| if (load_ehdr) | ||
| setNeedEhdr(); | ||
|
|
||
|
|
@@ -359,6 +378,7 @@ bool GNULDBackend::createProgramHdrs() { | |
| } | ||
|
|
||
| cur_flag = getSegmentFlag(cur->getFlags()); | ||
| bool CurIsExec = cur_flag & llvm::ELF::PF_X; | ||
|
|
||
| if (linkerScriptHasMemoryCommand && (*out)->epilog().hasRegion()) | ||
| cur_mem_region = (*out) | ||
|
|
@@ -445,7 +465,8 @@ bool GNULDBackend::createProgramHdrs() { | |
| } | ||
|
|
||
| if (isCurAlloc && (createPT_LOAD || last_section_needs_new_segment)) { | ||
| if (config().options().alignSegmentsToPage()) | ||
| bool ShouldPageAlign = ShouldPageAlignSegment(CurIsExec); | ||
| if (ShouldPageAlign) | ||
| alignAddress(vma, segAlign); | ||
| if (cur->isFixedAddr() && (vma != cur->addr())) { | ||
| config().raise(Diag::cannot_set_at_address) << cur->name(); | ||
|
|
@@ -483,7 +504,7 @@ bool GNULDBackend::createProgramHdrs() { | |
|
|
||
| // FIXME : remove this option alignSegmentsToPage | ||
| // Handle the case without any linker scripts, | ||
| if (config().options().alignSegmentsToPage()) | ||
| if (ShouldPageAlign) | ||
| alignAddress(pma, segAlign); | ||
|
|
||
| cur->setPaddr(pma); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # REQUIRES: x86 | ||
| # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o | ||
|
|
||
| ## -z noseparate-code. All PT_LOAD can have overlapping p_offset | ||
| ## ranges at runtime. | ||
| # RUN: %link -pie --no-align-segments --rosegment %t.o -o %t | ||
| # RUN: llvm-readelf -l %t | FileCheck --check-prefix=NONE %s | ||
| # NONE: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000200 0x000200 R E 0x1000 | ||
| # NONE-NEXT: LOAD 0x000200 0x0000000000000200 0x0000000000000200 0x000044 0x000044 R 0x1000 | ||
| # NONE-NEXT: LOAD 0x000244 0x0000000000000244 0x0000000000000244 0x000001 0x000001 R E 0x1000 | ||
| # NONE-NEXT: LOAD 0x000245 0x0000000000000245 0x0000000000000245 0x000001 0x000001 R 0x1000 | ||
| # NONE-NEXT: LOAD 0x000248 0x0000000000000248 0x0000000000000248 0x0000f1 0x0000f1 RW 0x1000 | ||
|
|
||
| ## -z separate-code makes text segment (RX) separate. | ||
| ## The two RW can have overlapping p_offset ranges at runtime. | ||
| # RUN: %link -pie --no-align-segments --rosegment %t.o -z separate-code -o %t | ||
| # RUN: llvm-readelf -l %t | FileCheck --check-prefix=CODE %s | ||
| # CODE: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000200 0x000200 R E 0x1000 | ||
| # CODE-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000044 0x000044 R 0x1000 | ||
| # CODE-NEXT: LOAD 0x002000 0x0000000000002000 0x0000000000002000 0x000001 0x000001 R E 0x1000 | ||
| # CODE-NEXT: LOAD 0x003000 0x0000000000003000 0x0000000000003000 0x000001 0x000001 R 0x1000 | ||
| # CODE-NEXT: LOAD 0x003008 0x0000000000003008 0x0000000000003008 0x0000f1 0x0000f1 RW 0x1000 | ||
|
|
||
| ## TODO: | ||
| ## -z separate-loadable-segments makes all segments separate. | ||
| # %link -pie --no-align-segments --rosegment %t.o -z separate-loadable-segments -o %t | ||
| # llvm-readelf -l %t | FileCheck --check-prefix=ALL %s | ||
| # ALL: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000200 0x000200 R E 0x1000 | ||
| # ALL-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000044 0x000044 R 0x1000 | ||
| # ALL-NEXT: LOAD 0x002000 0x0000000000002000 0x0000000000002000 0x000001 0x000001 R E 0x1000 | ||
| # ALL-NEXT: LOAD 0x003000 0x0000000000003000 0x0000000000003000 0x000001 0x000001 R 0x1000 | ||
| # ALL-NEXT: LOAD 0x004000 0x0000000000004000 0x0000000000004000 0x0000f1 0x0000f1 RW 0x1000 | ||
|
|
||
| nop | ||
|
|
||
| .section .rodata,"a" | ||
| .byte 0 | ||
|
|
||
| .data | ||
| .byte 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this be better?