Skip to content

Support z separate/no-separate code#707

Merged
quic-seaswara merged 1 commit intoqualcomm:mainfrom
quic-areg:sep-code
Feb 2, 2026
Merged

Support z separate/no-separate code#707
quic-seaswara merged 1 commit intoqualcomm:mainfrom
quic-areg:sep-code

Conversation

@quic-areg
Copy link
Copy Markdown
Contributor

-z separate-code puts the text segment in its
own pages disjoint from any other segments.

Copy link
Copy Markdown
Contributor

@quic-seaswara quic-seaswara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we import the tests from lld for this as part of this PR ?

Comment thread include/eld/Input/ZOption.h Outdated
Copy link
Copy Markdown
Contributor

@quic-seaswara quic-seaswara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have other options that are not compatible with -z seperate-code ?

How does using PHDR's, MEMORY, linker scripts, Adding LMA addresses, Using linker special directives (BYTE, QUAD, SQUAD, etc), orphan section placements work with this option ? Can you explore more with using the bfd linker ?

How does -z relro work this option ?

We might need to add a FAQ also for cases that people might want to consider this option for image size constraints, adding a new segment can cause increase in image size for example.

These analysis could be seperate bugs, and it might deserve an epic as applicable.

Does these -z options translate to reproduce command line option appropriately ?

Can we document incompatibilities ? and also document this option in detail.

I would prefer a test that can build and run in addition to a lit unit test.

You can decide to make some of these as follow ups with some discretion.

Comment thread lib/Target/CreateProgramHeaders.hpp
Copy link
Copy Markdown
Contributor

@partaror partaror left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This option is affecting all the targets, however, the test is added just for x86. Can we add a test in the common/Standalone subdirectory as well?

Comment thread include/eld/Input/ZOption.h Outdated
Comment thread lib/Target/CreateProgramHeaders.hpp
@quic-seaswara
Copy link
Copy Markdown
Contributor

I took some time to write test cases, it looks like there is some behavioral difference with these switches with linker script, omagic support, and shared library support.

@quic-areg can you please look into this usage, though we dont need to copy exact bfd behavior in cases where the linker gets confused and creates a segment that mixes R/RW/RWX.

Please see this test and let me know how we plan to address this both in diagnostics and other comments we have raised.

cat > 1.c << \!
int bss[10] = { 0 };
const int mydata[] = { 1, 2, 3, 4};
int foo() { return 0; }
int bar() { return 0; }
int baz() { return 0; }
!

cat > script.t << \!
SECTIONS {
  .foo : { *(.text.foo) }
  .rodata : { *(.rodata*) }
  .data : { *(.data*) }
  .bar : { *(.text.bar) }
  .baz : { *(.text.baz) }
  .bss : { *(.bss.*) }
}
!

clang -c -target x86_64 1.c -fPIC
echo "****************************************"
echo "No linker script ....."
echo "****************************************"
ld.bfd 1.o -z separate-code -o nols.1
readelf -l -W nols.1
echo "****************************************"
echo "No linker script ....omagic."
echo "****************************************"
ld.bfd 1.o -z separate-code -o nols.omagic -N
readelf -l -W nols.omagic
echo "****************************************"
echo "No linker script ....partial link."
echo "****************************************"
ld.bfd 1.o -z separate-code -o nols.partiallink -r
readelf -S -W nols.partiallink
echo "****************************************"
echo "No linker script ....shared library"
echo "****************************************"
ld.bfd 1.o -z separate-code -shared -o nols.shared.1
readelf -l -W nols.shared.1
echo "****************************************"
echo "No linker script ....."
echo "****************************************"
ld.bfd 1.o -z no-separate-code -o nols.no.1
readelf -l -W nols.no.1
echo "****************************************"
echo "No linker script ....omagic."
echo "****************************************"
ld.bfd 1.o -z no-separate-code -o nols.no.omagic -N
readelf -l -W nols.no.omagic
echo "****************************************"
echo "No linker script ....shared library"
echo "****************************************"
ld.bfd 1.o -z no-separate-code -shared -o nols.no.shared.1
readelf -l -W nols.no.shared.1
echo "****************************************"
echo "linker script ....."
echo "****************************************"
ld.bfd 1.o -z separate-code -o nols.1  -T script.t
readelf -l -W nols.1
echo "No linker script ....omagic."
ld.bfd 1.o -z separate-code -o nols.omagic -N -T script.t
readelf -l -W nols.omagic
echo "No linker script ....partial link."
ld.bfd 1.o -z separate-code -o nols.partiallink -r -T script.t
readelf -S -W nols.partiallink
echo "No linker script ....shared library"
ld.bfd 1.o -z separate-code -shared -o nols.shared.1 -T script.t
readelf -l -W nols.shared.1
echo "No linker script ....."
ld.bfd 1.o -z no-separate-code -o nols.no.1 -T script.t
readelf -l -W nols.no.1
echo "No linker script ....omagic."
ld.bfd 1.o -z no-separate-code -o nols.no.omagic -N -T script.t
readelf -l -W nols.no.omagic
echo "No linker script ....shared library"
ld.bfd 1.o -z no-separate-code -shared -o nols.no.shared.1 -T script.t
readelf -l -W nols.no.shared.1

@quic-areg
Copy link
Copy Markdown
Contributor Author

it looks like there is some behavioral difference with these switches with linker script, omagic support, and shared library support

It is expected that readelf -l would differ with the absence/presence of these options.

mixing -z separate-code with partial linking, omagic, or linker scripts does not make sense. We could warn for these combinations though neither lld nor bfd currently do.

@quic-seaswara
Copy link
Copy Markdown
Contributor

it looks like there is some behavioral difference with these switches with linker script, omagic support, and shared library support

It is expected that readelf -l would differ with the absence/presence of these options.

mixing -z separate-code with partial linking, omagic, or linker scripts does not make sense. We could warn for these combinations though neither lld nor bfd currently do.

Mixing -z seperate-code with omagic makes the linker choose omagic behavior, if you observe.

For shared libraries -z separate-code is not effective, if you see.

Since -z relro also bumps the page alignment for certain sections when they are seen in the program layout, doesn't it conflict ?

I am not sure why it does not make sense with linker scripts, does -z separate-code option always create aligned segments to page boundaries ?

@quic-areg
Copy link
Copy Markdown
Contributor Author

it looks like there is some behavioral difference with these switches with linker script, omagic support, and shared library support

It is expected that readelf -l would differ with the absence/presence of these options.
mixing -z separate-code with partial linking, omagic, or linker scripts does not make sense. We could warn for these combinations though neither lld nor bfd currently do.

Mixing -z seperate-code with omagic makes the linker choose omagic behavior, if you observe.

For shared libraries -z separate-code is not effective, if you see.

Since -z relro also bumps the page alignment for certain sections when they are seen in the program layout, doesn't it conflict ?

I am not sure why it does not make sense with linker scripts, does -z separate-code option always create aligned segments to page boundaries ?

Mixing -z seperate-code with omagic makes the linker choose omagic behavior, if you observe.

Yes I observed this. It makes no sense to request an RWX segment (omagic) along with a separate code segment. The options should not be mixed. both eld,lld,and bfd behave the same way when they are mixed (omagic takes precedence), if you observe:

ld.eld 1.o --omagic -z separate-code --omagic -o e.out --rosegment --no-align-segments 
ld.lld 1.o --omagic -z separate-code --omagic -o l.out  
ld.bfd 1.o --omagic -z separate-code --omagic -o b.out 
llvm-readelf -l e.out l.out b.out

  LOAD           0x000000 0x0000000000400000 0x0000000000400000 0x000138 0x000168 RWE 0x10

  LOAD           0x0000b0 0x00000000002000b0 0x00000000002000b0 0x0000b8 0x0000e8 RWE 0x10

  LOAD           0x0000b0 0x00000000004000b0 0x00000000004000b0 0x0000b8 0x0000e8 RWE 0x10

For shared libraries -z separate-code is not effective, if you see.

I guess I am missing something. Can you show an example?

here's my example, if you see

ld.eld -shared 1.o -z separate-code -o e.out --rosegment --no-align-segments
ld.lld -shared 1.o -z separate-code -o l.out
ld.bfd -shared 1.o -z separate-code -o b.out
llvm-readelf -l e.out l.out b.out

  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x000190 0x000190 R E 0x1000
  LOAD           0x001000 0x0000000000001000 0x0000000000001000 0x0000e4 0x0000e4 R   0x1000
  LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x000028 0x000028 R E 0x1000
  LOAD           0x003000 0x0000000000003000 0x0000000000003000 0x000088 0x000088 R   0x1000
  LOAD           0x003088 0x0000000000003088 0x0000000000003088 0x0000e0 0x000110 RW  0x1000

  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x00039c 0x00039c R   0x1000
  LOAD           0x001000 0x0000000000001000 0x0000000000001000 0x000028 0x000028 R E 0x1000
  LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x000070 0x001000 RW  0x1000
  LOAD           0x002070 0x0000000000003070 0x0000000000003070 0x000000 0x000028 RW  0x1000

  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x0002d8 0x0002d8 R   0x1000
  LOAD           0x001000 0x0000000000001000 0x0000000000001000 0x000028 0x000028 R E 0x1000
  LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x000088 0x000088 R   0x1000
  LOAD           0x002f40 0x0000000000003f40 0x0000000000003f40 0x0000c0 0x0000e8 RW  0x1000

The code segments are all in their own pages; it looks 'effective' to me. The other segments are allowed to overlap.

why are you adding --rosegment and --no-align-segments. can we just do -z separate-code?

eld page-aligns segments by default when there is no linker script present, so the effect of -z separate-code cannot be seen. eld also does not emit a separate ro segment, which the other linkers do. This is important because we need more segments to show that r/rw segments may overlap and that only code segments are aligned. this cannot be seen when there are only two segments, which I believe is the default

Since -z relro also bumps the page alignment for certain sections when they are seen in the program layout, doesn't it conflict ?

No I don't think so. Do you have an example?

I am not sure why it does not make sense with linker scripts, does -z separate-code option always create aligned segments to page boundaries ?

If the user has a linker script then they should own the layout/page alignment decisions. eg we page align segments by default when there is no linker script, but this is not turned on with linker scripts. lld does not honor -z separate-code with linker scripts for example.

does -z separate-code option always create aligned segments to page boundaries ?

starting code segments at page aligned offsets is one way to ensure that they are not co-resident on the same page as any other segment, and that seems to be how the other linkers implement it.

`-z separate-code` puts the text segment in its
own pages disjoint from any other segments.

Signed-off-by: quic-areg <aregmi@qti.qualcomm.com>
@quic-seaswara quic-seaswara merged commit 1f4aba8 into qualcomm:main Feb 2, 2026
2 of 5 checks passed
@quic-areg quic-areg deleted the sep-code branch March 11, 2026 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants