Skip to content

Commit 3aed704

Browse files
committed
Add setSymbolAddress plugin API and lit test coverage:
- LinkerWrapper::setSymbolAddress(Symbol, Addr): detaches a defined symbol from its fragment and assigns it an absolute (SHN_ABS) value, callable during AfterLayout. Limited to data symbols only and ensure address range is within that of the target architecture. Annotation is shown in the map file for affected symbols. Signed-off-by: Troy Curtiss <trcurtiss@gmail.com>
1 parent 4ad9180 commit 3aed704

32 files changed

Lines changed: 372 additions & 4 deletions

include/eld/Core/LinkerScript.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ class LinkerScript {
273273
void removeSymbolOp(plugin::LinkerWrapper *W, eld::Module *M,
274274
const ResolveInfo *S);
275275

276+
void setSymbolAddressOp(plugin::LinkerWrapper *W, eld::Module *M,
277+
const ResolveInfo *S, uint64_t Addr);
278+
276279
void updateRuleOp(plugin::LinkerWrapper *W, eld::Module *M, RuleContainer *R,
277280
ELFSection *S, const std::string &Annotation = "");
278281
void updateLinkStatsOp(plugin::LinkerWrapper *W, eld::Module *M,

include/eld/Core/Module.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,9 @@ class Module {
522522
// ---------------------------resetSymbol support -------------------------
523523
bool resetSymbol(ResolveInfo *, Fragment *F);
524524

525+
// ---------------------------setSymbolAddress support ---------------------
526+
bool setSymbolAddress(ResolveInfo *, uint64_t Addr);
527+
525528
// ---------------------------ImageLayoutChecksum support------------------
526529
uint64_t getImageLayoutChecksum() const;
527530

include/eld/Diagnostics/PluginDiags.inc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ DIAG(error_failed_to_add_sym_to_chunk, DiagnosticEngine::Error,
2222
"Failed to add symbol '%0' to chunk")
2323
DIAG(error_failed_to_reset_symbol, DiagnosticEngine::Error,
2424
"Failed to reset symbol '%0'")
25+
DIAG(error_failed_to_set_symbol_address, DiagnosticEngine::Error,
26+
"Failed to set address of symbol '%0' defined in '%1'")
27+
DIAG(error_set_symbol_address_on_function, DiagnosticEngine::Error,
28+
"Cannot set address of symbol '%0' defined in '%1' because it is a "
29+
"function symbol; setSymbolAddress is only allowed on data symbols")
30+
DIAG(error_set_symbol_address_out_of_range, DiagnosticEngine::Error,
31+
"Cannot set address of symbol '%0' defined in '%1' to 0x%2 because it "
32+
"exceeds the maximum address 0x%3 supported by the target")
2533
DIAG(error_failed_to_insert_rule, DiagnosticEngine::Error,
2634
"Failed to insert rule")
2735
DIAG(error_invalid_use, DiagnosticEngine::Error, "Invalid Use")

include/eld/LayoutMap/LDYAML.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct Symbol {
4747
SymbolScope Scope;
4848
llvm::yaml::Hex32 Size;
4949
llvm::yaml::Hex64 Value;
50+
std::string SetAddressBy;
5051
};
5152
// Display Input file if it is used or not.
5253
struct InputFile {

include/eld/LayoutMap/LayoutInfo.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ class LayoutInfo {
151151

152152
typedef llvm::DenseMap<const ResolveInfo *, PluginOp *> RemoveSymbolOpsMapT;
153153

154+
typedef llvm::DenseMap<const ResolveInfo *, PluginOp *>
155+
SetSymbolAddressOpsMapT;
156+
154157
typedef llvm::DenseMap<ELFSection *, std::vector<PluginOp *>> SectionOpsMapT;
155158

156159
typedef llvm::DenseMap<const Fragment *, std::vector<PluginOp *>>
@@ -309,6 +312,9 @@ class LayoutInfo {
309312

310313
void recordRemoveSymbol(plugin::LinkerWrapper *W, RemoveSymbolPluginOp *O);
311314

315+
void recordSetSymbolAddress(plugin::LinkerWrapper *W,
316+
SetSymbolAddressPluginOp *O);
317+
312318
void recordRelocationData(plugin::LinkerWrapper *W,
313319
RelocationDataPluginOp *O);
314320

@@ -358,6 +364,10 @@ class LayoutInfo {
358364

359365
const RemoveSymbolOpsMapT &getRemovedSymbols() { return RemovedSymbols; }
360366

367+
const SetSymbolAddressOpsMapT &getSetSymbolAddressOps() {
368+
return SetSymbolAddressOps;
369+
}
370+
361371
ChunkOpsMapT &getChunkOps() { return ChunkOps; }
362372

363373
SectionOpsMapT &getSectionOps() { return ChangeOutputSectionOps; }
@@ -431,6 +441,8 @@ class LayoutInfo {
431441
SectionOpsMapT ChangeOutputSectionOps;
432442
ChunkOpsMapT ChunkOps;
433443
RemoveSymbolOpsMapT RemovedSymbols;
444+
445+
SetSymbolAddressOpsMapT SetSymbolAddressOps;
434446
llvm::DenseSet<plugin::LinkerWrapper *> Plugins;
435447
// FIXME: Why do member names here start from underscore?
436448
// Names starting from an underscore is generally used to

include/eld/LayoutMap/YamlLayoutPrinter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ class YamlLayoutPrinter {
5959
void getTrampolineMap(eld::Module &Module,
6060
std::vector<eld::LDYAML::TrampolineInfo> &R);
6161

62+
std::string getSetAddressByStr(const ResolveInfo *R) const;
63+
6264
private:
6365
std::vector<CommandLineDefault> Defaults;
6466
std::string CommandLine;

include/eld/Plugin/PluginActivityLog.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class PluginActivityLog {
5656

5757
llvm::json::Object toJSON(const RemoveSymbolPluginOp &P) const;
5858

59+
llvm::json::Object toJSON(const SetSymbolAddressPluginOp &P) const;
60+
5961
llvm::json::Object toJSON(const RelocationDataPluginOp &P) const;
6062

6163
llvm::json::Object toJSON(const UpdateLinkStatsPluginOp &P) const;

include/eld/Plugin/PluginOp.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ class PluginOp {
3737
UpdateRule,
3838
RelocationData,
3939
UpdateLinkState,
40-
SortInputSectionsForMerging
40+
SortInputSectionsForMerging,
41+
SetSymbolAddress
4142
};
4243

4344
explicit PluginOp(plugin::LinkerWrapper *, PluginOpType T,
@@ -67,6 +68,7 @@ class PluginOp {
6768
ADD_CASE(RelocationData)
6869
ADD_CASE(UpdateLinkState)
6970
ADD_CASE(SortInputSectionsForMerging)
71+
ADD_CASE(SetSymbolAddress)
7072
}
7173
#undef ADD_CASE
7274
return "Unknown";
@@ -194,6 +196,26 @@ class RemoveSymbolPluginOp : public PluginOp {
194196
const ResolveInfo *RemovedSymbol;
195197
};
196198

199+
class SetSymbolAddressPluginOp : public PluginOp {
200+
public:
201+
SetSymbolAddressPluginOp(plugin::LinkerWrapper *W, const eld::ResolveInfo *S,
202+
uint64_t Addr);
203+
204+
static bool classof(const PluginOp *P) {
205+
return P->getPluginOpType() == PluginOpType::SetSymbolAddress;
206+
}
207+
208+
std::string getPluginOpStr() const override { return "SA"; }
209+
210+
const ResolveInfo *getSymbol() const { return Symbol; }
211+
212+
uint64_t getAddress() const { return Address; }
213+
214+
private:
215+
const ResolveInfo *Symbol;
216+
uint64_t Address;
217+
};
218+
197219
class RelocationDataPluginOp : public PluginOp {
198220
public:
199221
RelocationDataPluginOp(plugin::LinkerWrapper *W, const eld::Relocation *R,

include/eld/PluginAPI/Diagnostics.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ DLL_A_EXPORT DiagnosticEntry::DiagIDType warn_no_section_overrides_found();
1717
DLL_A_EXPORT DiagnosticEntry::DiagIDType error_failed_to_register_reloc();
1818
DLL_A_EXPORT DiagnosticEntry::DiagIDType error_failed_to_add_sym_to_chunk();
1919
DLL_A_EXPORT DiagnosticEntry::DiagIDType error_failed_to_reset_symbol();
20+
DLL_A_EXPORT DiagnosticEntry::DiagIDType error_failed_to_set_symbol_address();
2021
DLL_A_EXPORT DiagnosticEntry::DiagIDType error_failed_to_insert_rule();
2122
DLL_A_EXPORT DiagnosticEntry::DiagIDType error_invalid_use();
2223
DLL_A_EXPORT DiagnosticEntry::DiagIDType error_empty_data();

include/eld/PluginAPI/LinkerWrapper.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,33 @@ class DLL_A_EXPORT LinkerWrapper {
571571
/// be reset is a defined symbol with an initial value.
572572
eld::Expected<void> resetSymbol(plugin::Symbol S, Chunk C);
573573

574+
/// Detach symbol S from its current fragment (if any) and make it an
575+
/// absolute symbol with value Addr. The symbol's output section index
576+
/// becomes SHN_ABS, and its value is no longer derived from any chunk's
577+
/// placement.
578+
///
579+
/// Unlike resetSymbol(), this works on already-defined symbols.
580+
///
581+
/// \param S Symbol whose address is to be set.
582+
/// \param Addr Absolute value to assign to the symbol.
583+
///
584+
/// \note This function must only be used in the \em AfterLayout link
585+
/// state, i.e. after layout, garbage-collection, and relaxation have
586+
/// converged, and before the symbol table and relocations are finalized
587+
/// and emitted.
588+
///
589+
/// \note Reassigning a symbol's address this way does not change the
590+
/// address range that the linker's virtual-address overlap check
591+
/// associates with the symbol's original output section. If the new
592+
/// address could fall inside another section's address range, declare
593+
/// the symbol's output section with the \c INFO, \c COPY, \c DSECT, or
594+
/// \c OVERLAY linker script section type. These types are equivalent in
595+
/// ELD: each removes the section from the overlap check (and from
596+
/// PT_LOAD segment placement) by clearing \c SHF_ALLOC on the section,
597+
/// which is recommended whenever the section's addresses are bookkeeping
598+
/// only and are not meant to be loaded at runtime.
599+
eld::Expected<void> setSymbolAddress(plugin::Symbol S, uint64_t Addr);
600+
574601
/// Create and return a Use for a Chunk, and add it to the Chunk.
575602
eld::Expected<Use> createAndAddUse(Chunk C, off_t Offset,
576603
uint32_t RelocationType, plugin::Symbol S,

0 commit comments

Comments
 (0)