-
Notifications
You must be signed in to change notification settings - Fork 63
test: add tests and docs for section address linker options #1145
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 3 commits
3eba23f
04c5330
ed54426
e9bd2e0
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 |
|---|---|---|
|
|
@@ -277,6 +277,28 @@ alignment specified in :code:`ALIGN`. | |
| There are various linker command-line options for setting output section | ||
| VMA: ``-Tbss``, ``-Tdata``, ``-Ttext`` and ``--section-start``. | ||
|
|
||
| --section-start=sectionname=org | ||
| Assigns the absolute address org to the named output section. | ||
| You may use this option multiple times to place multiple sections at specific addresses. | ||
|
|
||
| -Ttext=org | ||
| Same as ``--section-start`` with ``.text`` as the section name. | ||
|
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. What if there is no .text section ? |
||
|
|
||
| -Tdata=org | ||
| Same as ``--section-start`` with ``.data`` as the section name. | ||
|
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. Same as previous, what if there is no data section ? |
||
|
|
||
| -Tbss=org | ||
| Same as ``--section-start`` with ``.bss`` as the section name. | ||
|
|
||
| -Ttext-segment=org | ||
| When creating an ELF executable, it sets the address of the first byte of the text segment. | ||
|
|
||
| -Trodata-segment=org | ||
| When creating an ELF executable or shared object for a target where the read-only data is in its own segment separate from the executable text, it sets the address of the first byte of the read-only data segment. | ||
|
|
||
| -Tldata-segment=org | ||
| When creating an ELF executable or shared object for the x86-64 medium memory model, it sets the address of the first byte of the ldata segment. | ||
|
|
||
| When both the linker script and the command line specify an output-section address, | ||
| the command-line option takes precedence and overrides the script's explicit address. | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -746,6 +746,13 @@ class GeneralOptions { | |
| const std::optional<uint64_t> &imageBase() const { return ImageBase; } | ||
|
|
||
| void setImageBase(uint64_t Value) { ImageBase = Value; } | ||
|
|
||
| const std::optional<uint64_t> &textSegment() const { return TextSegment; } | ||
|
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. Why is the PR for adding tests and docs modifying functionality?
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. Good point.
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. I think what @parth-07 is mentioning is the commit message says adding tests but now we are implementing support. The issue needs to be properly documented and also the commit message.
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. I'll update the commit message. Thanks for clarifying.
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 convert these functions to use verbs, get/set. I recommend using getTextSegmentAddress(), it would be very clear. Also update the text map file so that an user inspecting the text map file can know what is going on. |
||
| void setTextSegment(uint64_t Value) { TextSegment = Value; } | ||
| const std::optional<uint64_t> &rodataSegment() const { return RodataSegment; } | ||
| void setRodataSegment(uint64_t Value) { RodataSegment = Value; } | ||
| const std::optional<uint64_t> &ldataSegment() const { return LdataSegment; } | ||
| void setLdataSegment(uint64_t Value) { LdataSegment = Value; } | ||
|
|
||
| /// entry point | ||
| const std::string &entry() const; | ||
|
|
@@ -1377,6 +1384,9 @@ class GeneralOptions { | |
| std::vector<std::string> LTOOutputFile; | ||
| bool BCompactDyn = false; // z,compactdyn | ||
| std::optional<uint64_t> ImageBase; // --image-base=value | ||
| std::optional<uint64_t> TextSegment; | ||
| std::optional<uint64_t> RodataSegment; | ||
| std::optional<uint64_t> LdataSegment; | ||
| std::string Entry; | ||
| SymbolRenameMap SymbolRenames; | ||
| AddressMapType AddressMap; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -225,6 +225,16 @@ defm Ttext_segment | |
| "Specify an address for the .text-segment segment">, | ||
| MetaVarName<"<address>">, | ||
| Group<grp_scriptopts>; | ||
| defm Trodata_segment | ||
| : dashEqWithOpt<"Trodata-segment", "Trodata-segment", "Trodata_segment", | ||
| "Specify an address for the .rodata-segment segment">, | ||
|
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 you reword this ? Is there anything like .rodata-segment ? |
||
| MetaVarName<"<address>">, | ||
| Group<grp_scriptopts>; | ||
| defm Tldata_segment | ||
| : dashEqWithOpt<"Tldata-segment", "Tldata-segment", "Tldata_segment", | ||
| "Specify an address for the .ldata-segment segment">, | ||
|
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. What is .ldata-segment ? Can you simplify this and reword ? |
||
| MetaVarName<"<address>">, | ||
| Group<grp_scriptopts>; | ||
| defm Tdata | ||
| : smDash<"Tdata", "Tdata", "Specify an address for the .data section">, | ||
| MetaVarName<"<address>">, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -858,6 +858,27 @@ bool GnuLdDriver::processOptions(llvm::opt::InputArgList &Args) { | |
| Config.options().addressMap().insert(std::make_pair(".text", addr)); | ||
| } | ||
|
|
||
| // -Ttext-segment=value | ||
| if (llvm::opt::Arg *arg = Args.getLastArg(T::Ttext_segment)) { | ||
| uint64_t addr = 0; | ||
| if (!llvm::StringRef(arg->getValue()).getAsInteger(0, addr)) | ||
|
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. We should report an error if the argument is incorrect for the new options added. |
||
| Config.options().setTextSegment(addr); | ||
|
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. It might be useful to give a warning with linker scripts if the user used a linker script and users using this option.
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. Also add a diagnostic if the value is not represented as a integer or does not fit the target address space. For example using a 64bit address on a 32bit image. |
||
| } | ||
|
|
||
| // -Trodata-segment=value | ||
| if (llvm::opt::Arg *arg = Args.getLastArg(T::Trodata_segment)) { | ||
| uint64_t addr = 0; | ||
| if (!llvm::StringRef(arg->getValue()).getAsInteger(0, addr)) | ||
| Config.options().setRodataSegment(addr); | ||
|
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. Is this handled in program layout ?
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. It is currently parsed and stored but not yet handled in program layout. Would you like me to implement it in this PR or open a separate issue for it? |
||
| } | ||
|
|
||
| // -Tldata-segment=value | ||
| if (llvm::opt::Arg *arg = Args.getLastArg(T::Tldata_segment)) { | ||
| uint64_t addr = 0; | ||
| if (!llvm::StringRef(arg->getValue()).getAsInteger(0, addr)) | ||
| Config.options().setLdataSegment(addr); | ||
|
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. Is this handled in program layout ?
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. It is currently parsed and stored but not yet handled in program layout. Would you like me to implement it in this PR or open a separate issue for it? |
||
| } | ||
|
|
||
| // --dynamic-list | ||
| for (auto *Arg : Args.filtered(T::dynamic_list)) | ||
| Config.options().getDynList().emplace(Arg->getValue()); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4060,6 +4060,8 @@ bool GNULDBackend::symbolNeedsCopyReloc(const Relocation &pReloc, | |
| } | ||
|
|
||
| uint64_t GNULDBackend::getImageBase(bool HasInterp, bool LoadEHdr) const { | ||
| if (auto TextSegment = config().options().textSegment()) | ||
| return *TextSegment; | ||
|
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. Does -Ttext-segment override linker script assignment ?
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. I tested this, when both
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. Pinging on this - wanted to confirm the expected behavior before making any further changes to GNULDBackend.cpp.
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. Thanks for confirming. Please go ahead. |
||
| if (auto ImageBase = config().options().imageBase()) | ||
| return *ImageBase; | ||
| return m_pInfo->startAddr( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| int data_var = 1; | ||
| int bss_var; | ||
| int foo() { return 0; } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| SECTIONS { | ||
| .text : { *(.text*) } | ||
| .data : { *(.data*) *(.sdata*) } | ||
| .bss : { *(.bss*) *(.sbss*) } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| #---Ttext.test--------------------------- Executable,LS -----------------# | ||
| #BEGIN_COMMENT | ||
| # This checks for options -Ttext, -Tdata and -Tbss that are handled in the linker. | ||
| #END_COMMENT | ||
| #START_TEST | ||
| RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.o | ||
| RUN: %link %linkopts %t1.o -o %t1.out -Ttext=0x10000000 | ||
| RUN: %readelf -S %t1.out -W | %filecheck %s --check-prefix=CHECK-TEXT | ||
| CHECK-TEXT: .text {{.*}} {{0*}}10000000 | ||
| RUN: %link %linkopts %t1.o -T %p/Inputs/force-sections.t -o %t2.out -Tdata=0x20000000 | ||
| RUN: %readelf -S %t2.out -W | %filecheck %s --check-prefix=CHECK-DATA | ||
| CHECK-DATA: .data {{.*}} {{0*}}20000000 | ||
| RUN: %link %linkopts %t1.o -T %p/Inputs/force-sections.t -o %t3.out -Tbss=0x30000000 | ||
| RUN: %readelf -S %t3.out -W | %filecheck %s --check-prefix=CHECK-BSS | ||
| CHECK-BSS: .bss {{.*}} {{0*}}30000000 | ||
| #END_TEST |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| int foo() { return 0; } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #---TtextSegment.test--------------------------- Executable,LS -----------------# | ||
| #BEGIN_COMMENT | ||
| # This checks for option -Ttext-segment that is handled in the linker. | ||
| #END_COMMENT | ||
| #START_TEST | ||
| RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.o | ||
| RUN: %link %linkopts %t1.o -o %t1.out -Ttext-segment=0x10000000 | ||
| RUN: %readelf -l %t1.out -W | %filecheck %s --check-prefix=CHECK-TEXT-SEGMENT | ||
| CHECK-TEXT-SEGMENT: LOAD {{.*}} 0x{{0*}}10000000 | ||
| #END_TEST |
|
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. Why is this test hexagon specific? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #---SectionStart.test--------------------------- Executable,LS -----------------# | ||
| #BEGIN_COMMENT | ||
| # This checks for option --section-start that is being handled in the linker. | ||
| #END_COMMENT | ||
| #START_TEST | ||
| RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.1.o | ||
| RUN: %link %linkopts %t1.1.o -o %t2.out --section-start .text=0xF0000000 | ||
| RUN: %readelf -s %t2.out -W | %filecheck %s | ||
| #CHECK: f0000000 | ||
| #END_TEST |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| int data_var = 1; | ||
| int foo() { return 0; } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #---TldataSegment.test--------------------------- Executable,LS -----------------# | ||
| #BEGIN_COMMENT | ||
| # This checks for option -Tldata-segment that is handled in the linker. | ||
| #END_COMMENT | ||
| #START_TEST | ||
| RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.o | ||
| RUN: %link %linkopts %t1.o -o %t1.out -Tldata-segment=0x30000000 | ||
| RUN: %readelf -l %t1.out -W | %filecheck %s --check-prefix=CHECK-LDATA-SEGMENT | ||
| CHECK-LDATA-SEGMENT: LOAD {{.*}} 0x{{0*}}30000000 | ||
| #END_TEST |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| const int rodata_var = 1; | ||
| int foo() { return 0; } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #---TrodataSegment.test--------------------------- Executable,LS -----------------# | ||
| #BEGIN_COMMENT | ||
| # This checks for option -Trodata-segment that is handled in the linker. | ||
| #END_COMMENT | ||
| #START_TEST | ||
| RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.o | ||
| RUN: %link %linkopts %t1.o -o %t1.out -Trodata-segment=0x20000000 | ||
| RUN: %readelf -l %t1.out -W | %filecheck %s --check-prefix=CHECK-RODATA-SEGMENT | ||
| CHECK-RODATA-SEGMENT: LOAD {{.*}} 0x{{0*}}20000000 | ||
| #END_TEST |
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.
What happens if you specify the --section-start with the same section name multiple times ? Can we add that to the documentation ?