Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/userguide/documentation/layout.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 specified address to the 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.

-Tdata=org
Same as ``--section-start`` with ``.data`` as the section name.

-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.

Expand Down
10 changes: 10 additions & 0 deletions include/eld/Config/GeneralOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
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;
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions include/eld/Driver/GnuLinkerOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">,
MetaVarName<"<address>">,
Group<grp_scriptopts>;
defm Tldata_segment
: dashEqWithOpt<"Tldata-segment", "Tldata-segment", "Tldata_segment",
"Specify an address for the .ldata-segment segment">,
MetaVarName<"<address>">,
Group<grp_scriptopts>;
defm Tdata
: smDash<"Tdata", "Tdata", "Specify an address for the .data section">,
MetaVarName<"<address>">,
Expand Down
21 changes: 21 additions & 0 deletions lib/LinkerWrapper/GnuLdDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Config.options().setTextSegment(addr);
}

// -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);
}

// -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);
}

// --dynamic-list
for (auto *Arg : Args.filtered(T::dynamic_list))
Config.options().getDynList().emplace(Arg->getValue());
Expand Down
2 changes: 2 additions & 0 deletions lib/Target/GNULDBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3847,6 +3847,8 @@ bool GNULDBackend::symbolNeedsCopyReloc(const Relocation &pReloc,
}

uint64_t GNULDBackend::getImageBase(bool HasInterp, bool LoadEHdr) const {
if (auto TextSegment = config().options().textSegment())
return *TextSegment;
if (auto ImageBase = config().options().imageBase())
return *ImageBase;
return m_pInfo->startAddr(
Expand Down
3 changes: 3 additions & 0 deletions test/Common/standalone/CommandLine/Ttext/Inputs/1.c
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*) }
}
16 changes: 16 additions & 0 deletions test/Common/standalone/CommandLine/Ttext/Ttext.test
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
1 change: 1 addition & 0 deletions test/Common/standalone/CommandLine/TtextSegment/Inputs/1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int foo() { return 0; }
10 changes: 10 additions & 0 deletions test/Common/standalone/CommandLine/TtextSegment/TtextSegment.test
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
2 changes: 2 additions & 0 deletions test/Common/standalone/VersionScriptAnonymousMixed/Inputs/1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
void foo() {}
void bar() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
VER_1.0 {
global: foo;
};
{
global: bar;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
UNSUPPORTED: x86
#---VersionScriptAnonymousMixed.test--------------------- SharedLibrary,VS------------------#
#BEGIN_COMMENT
# Test that an error is emitted when an anonymous version definition
# is used in combination with other named version definitions
# in a version script.
# See: https://github.com/qualcomm/eld/issues/1124
#END_COMMENT

RUN: %clang %clangopts -c -fpic %p/Inputs/1.c -o %t1.o
RUN: %not %link %linkopts -shared -o %t1.so %t1.o --version-script=%p/Inputs/vs_mixed 2>&1 | %filecheck %s

CHECK: Error: {{.*}}: anonymous version definition is used in combination with other version definitions

10 changes: 10 additions & 0 deletions test/Hexagon/standalone/CommandLine/SectionStart/SectionStart.test
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
2 changes: 2 additions & 0 deletions test/x86_64/standalone/CommandLine/TldataSegment/Inputs/1.c
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
2 changes: 2 additions & 0 deletions test/x86_64/standalone/CommandLine/TrodataSegment/Inputs/1.c
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