Section 8.4 Relocation Operations could benefit from clarifying the semantics of the LDG(S) operation used in the extended relocation definitions. In particular, it would be helpful to clarify:
-
whether LDG(S) is an abstract semantic operation ("materialize the correct logical tag for S") or whether it normatively requires execution of the architectural ldg instruction;
-
the expected observable behavior of LDG(S) when S refers to an allocation that is not allocation-tagged (i.e. whether the resulting pointer is expected to carry logical tag 0).
The following wording is proposed for the definition of LDG(pointer):
LDG(pointer) denotes the operation of materializing a pointer whose address equals pointer and whose logical tag equals the allocation tag associated with the allocation containing pointer. If the referenced allocation is not allocation-tagged the resulting logical tag is zero.
Context and details
Section 8.4 Relocation Operations extends the following relocation types:
| ELF64 Relocation |
Base semantics |
MemtagABI semantics |
R_AARCH64_ABS64 |
S + A |
LDG(S) + A |
R_AARCH64_GLOB_DAT |
S + A |
LDG(S) + A |
R_AARCH64_RELATIVE |
Delta + A |
LDG(Delta + A + *P) - *P |
The specification also defines:
"LDG(pointer) is an instruction for the run-time environment to use the ldg instruction on pointer to materialize the correct logical tag for a symbol."
It is not entirely clear whether LDG(S) is intended to be interpreted as an abstract semantic operation or as a normative requirement to execute the architectural ldg instruction.
These relocation types are also generated for function pointers. For example:
using FnT = void();
extern "C" [[gnu::visibility("default")]] void defaultFunction() {}
constinit FnT* defaultFunctionPtr = &defaultFunction; // R_AARCH64_ABS64
In this example, the relocation symbol S is the address of defaultFunction in the executable .text section.
The ARM Architecture Reference Manual defines ldg as a load operation:
accdesc = CreateAccDescLDGSTG(MemOp_LOAD, stzgm, t);
...
tag = AArch64_MemTag(address, accdesc);
At the same time, the architecture specifies that reading the allocation tag of a non-allocation-tagged address yields allocation tag 0:
if accdesc.tagaccess && memtagtype == MemTag_AllocationTagged then
(memstatus, tag) = PhysMemTagRead(memaddrdesc, accdesc);
return (tag, memaddrdesc, memstatus);
...
else
// Otherwise read the tag as zero
tag = '0000';
return (tag, memaddrdesc, memstatus);
end;
The ambiguity arises because ldg cannot be executed on every symbol address. The instruction is defined as a load operation and therefore performs read permission checks. Consequently, executing ldg on an execute-only (XOM) mapping faults.
On the other hand, the library pseudocode for ldg specifies that reading the allocation tag of a non-allocation-tagged address returns allocation tag 0. Therefore, for symbols known not to be allocation-tagged, the observable result of LDG(S) can be obtained without executing the ldg instruction.
It is currently in the spec implicitly, as the spec does not require to always match the LDG(pointer) operation to the ldg instruction.
However defining LDG(S) explicitly as a semantic operation, together with its observable behavior (including the result for non-allocation-tagged memory), would remove any possible ambiguity while allowing implementations to produce the required result in an equivalent manner.
Section 8.4 Relocation Operations could benefit from clarifying the semantics of the
LDG(S)operation used in the extended relocation definitions. In particular, it would be helpful to clarify:whether
LDG(S)is an abstract semantic operation ("materialize the correct logical tag forS") or whether it normatively requires execution of the architecturalldginstruction;the expected observable behavior of
LDG(S)whenSrefers to an allocation that is not allocation-tagged (i.e. whether the resulting pointer is expected to carry logical tag0).The following wording is proposed for the definition of
LDG(pointer):Context and details
Section 8.4 Relocation Operations extends the following relocation types:
R_AARCH64_ABS64S + ALDG(S) + AR_AARCH64_GLOB_DATS + ALDG(S) + AR_AARCH64_RELATIVEDelta + ALDG(Delta + A + *P) - *PThe specification also defines:
It is not entirely clear whether
LDG(S)is intended to be interpreted as an abstract semantic operation or as a normative requirement to execute the architecturalldginstruction.These relocation types are also generated for function pointers. For example:
In this example, the relocation symbol
Sis the address ofdefaultFunctionin the executable.textsection.The ARM Architecture Reference Manual defines
ldgas a load operation:At the same time, the architecture specifies that reading the allocation tag of a non-allocation-tagged address yields allocation tag
0:The ambiguity arises because
ldgcannot be executed on every symbol address. The instruction is defined as a load operation and therefore performs read permission checks. Consequently, executingldgon an execute-only (XOM) mapping faults.On the other hand, the library pseudocode for
ldgspecifies that reading the allocation tag of a non-allocation-tagged address returns allocation tag0. Therefore, for symbols known not to be allocation-tagged, the observable result ofLDG(S)can be obtained without executing theldginstruction.It is currently in the spec implicitly, as the spec does not require to always match the
LDG(pointer)operation to theldginstruction.However defining
LDG(S)explicitly as a semantic operation, together with its observable behavior (including the result for non-allocation-tagged memory), would remove any possible ambiguity while allowing implementations to produce the required result in an equivalent manner.