1 //===- ARM.cpp ------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "InputFiles.h"
10 #include "OutputSections.h"
11 #include "SymbolTable.h"
13 #include "SyntheticSections.h"
15 #include "lld/Common/ErrorHandler.h"
16 #include "lld/Common/Filesystem.h"
17 #include "llvm/BinaryFormat/ELF.h"
18 #include "llvm/Support/Endian.h"
21 using namespace llvm::support::endian
;
22 using namespace llvm::support
;
23 using namespace llvm::ELF
;
25 using namespace lld::elf
;
26 using namespace llvm::object
;
29 class ARM final
: public TargetInfo
{
32 uint32_t calcEFlags() const override
;
33 RelExpr
getRelExpr(RelType type
, const Symbol
&s
,
34 const uint8_t *loc
) const override
;
35 RelType
getDynRel(RelType type
) const override
;
36 int64_t getImplicitAddend(const uint8_t *buf
, RelType type
) const override
;
37 void writeGotPlt(uint8_t *buf
, const Symbol
&s
) const override
;
38 void writeIgotPlt(uint8_t *buf
, const Symbol
&s
) const override
;
39 void writePltHeader(uint8_t *buf
) const override
;
40 void writePlt(uint8_t *buf
, const Symbol
&sym
,
41 uint64_t pltEntryAddr
) const override
;
42 void addPltSymbols(InputSection
&isec
, uint64_t off
) const override
;
43 void addPltHeaderSymbols(InputSection
&isd
) const override
;
44 bool needsThunk(RelExpr expr
, RelType type
, const InputFile
*file
,
45 uint64_t branchAddr
, const Symbol
&s
,
46 int64_t a
) const override
;
47 uint32_t getThunkSectionSpacing() const override
;
48 bool inBranchRange(RelType type
, uint64_t src
, uint64_t dst
) const override
;
49 void relocate(uint8_t *loc
, const Relocation
&rel
,
50 uint64_t val
) const override
;
52 enum class CodeState
{ Data
= 0, Thumb
= 2, Arm
= 4 };
55 static DenseMap
<InputSection
*, SmallVector
<const Defined
*, 0>> sectionMap
{};
59 relativeRel
= R_ARM_RELATIVE
;
60 iRelativeRel
= R_ARM_IRELATIVE
;
61 gotRel
= R_ARM_GLOB_DAT
;
62 pltRel
= R_ARM_JUMP_SLOT
;
63 symbolicRel
= R_ARM_ABS32
;
64 tlsGotRel
= R_ARM_TLS_TPOFF32
;
65 tlsModuleIndexRel
= R_ARM_TLS_DTPMOD32
;
66 tlsOffsetRel
= R_ARM_TLS_DTPOFF32
;
70 trapInstr
= {0xd4, 0xd4, 0xd4, 0xd4};
72 defaultMaxPageSize
= 65536;
75 uint32_t ARM::calcEFlags() const {
76 // The ABIFloatType is used by loaders to detect the floating point calling
78 uint32_t abiFloatType
= 0;
80 // Set the EF_ARM_BE8 flag in the ELF header, if ELF file is big-endian
84 if (config
->armVFPArgs
== ARMVFPArgKind::Base
||
85 config
->armVFPArgs
== ARMVFPArgKind::Default
)
86 abiFloatType
= EF_ARM_ABI_FLOAT_SOFT
;
87 else if (config
->armVFPArgs
== ARMVFPArgKind::VFP
)
88 abiFloatType
= EF_ARM_ABI_FLOAT_HARD
;
90 if (!config
->isLE
&& config
->armBe8
)
93 // We don't currently use any features incompatible with EF_ARM_EABI_VER5,
94 // but we don't have any firm guarantees of conformance. Linux AArch64
95 // kernels (as of 2016) require an EABI version to be set.
96 return EF_ARM_EABI_VER5
| abiFloatType
| armBE8
;
99 RelExpr
ARM::getRelExpr(RelType type
, const Symbol
&s
,
100 const uint8_t *loc
) const {
103 case R_ARM_MOVW_ABS_NC
:
105 case R_ARM_THM_MOVW_ABS_NC
:
106 case R_ARM_THM_MOVT_ABS
:
107 case R_ARM_THM_ALU_ABS_G0_NC
:
108 case R_ARM_THM_ALU_ABS_G1_NC
:
109 case R_ARM_THM_ALU_ABS_G2_NC
:
110 case R_ARM_THM_ALU_ABS_G3
:
112 case R_ARM_THM_JUMP8
:
113 case R_ARM_THM_JUMP11
:
120 case R_ARM_THM_JUMP19
:
121 case R_ARM_THM_JUMP24
:
128 // GOT(S) + A - GOT_ORG
137 return config
->target1Rel
? R_PC
: R_ABS
;
139 if (config
->target2
== Target2Policy::Rel
)
141 if (config
->target2
== Target2Policy::Abs
)
146 case R_ARM_TLS_LDM32
:
148 case R_ARM_TLS_LDO32
:
150 case R_ARM_BASE_PREL
:
152 // FIXME: currently B(S) assumed to be .got, this may not hold for all
155 case R_ARM_MOVW_PREL_NC
:
156 case R_ARM_MOVT_PREL
:
158 case R_ARM_THM_MOVW_PREL_NC
:
159 case R_ARM_THM_MOVT_PREL
:
161 case R_ARM_ALU_PC_G0
:
162 case R_ARM_ALU_PC_G0_NC
:
163 case R_ARM_ALU_PC_G1
:
164 case R_ARM_ALU_PC_G1_NC
:
165 case R_ARM_ALU_PC_G2
:
166 case R_ARM_LDR_PC_G0
:
167 case R_ARM_LDR_PC_G1
:
168 case R_ARM_LDR_PC_G2
:
169 case R_ARM_LDRS_PC_G0
:
170 case R_ARM_LDRS_PC_G1
:
171 case R_ARM_LDRS_PC_G2
:
172 case R_ARM_THM_ALU_PREL_11_0
:
176 case R_ARM_MOVW_BREL_NC
:
177 case R_ARM_MOVW_BREL
:
178 case R_ARM_MOVT_BREL
:
179 case R_ARM_THM_MOVW_BREL_NC
:
180 case R_ARM_THM_MOVW_BREL
:
181 case R_ARM_THM_MOVT_BREL
:
188 // V4BX is just a marker to indicate there's a "bx rN" instruction at the
189 // given address. It can be used to implement a special linker mode which
190 // rewrites ARMv4T inputs to ARMv4. Since we support only ARMv4 input and
191 // not ARMv4 output, we can just ignore it.
194 error(getErrorLocation(loc
) + "unknown relocation (" + Twine(type
) +
195 ") against symbol " + toString(s
));
200 RelType
ARM::getDynRel(RelType type
) const {
201 if ((type
== R_ARM_ABS32
) || (type
== R_ARM_TARGET1
&& !config
->target1Rel
))
206 void ARM::writeGotPlt(uint8_t *buf
, const Symbol
&) const {
207 write32(buf
, in
.plt
->getVA());
210 void ARM::writeIgotPlt(uint8_t *buf
, const Symbol
&s
) const {
211 // An ARM entry is the address of the ifunc resolver function.
212 write32(buf
, s
.getVA());
215 // Long form PLT Header that does not have any restrictions on the displacement
216 // of the .plt from the .got.plt.
217 static void writePltHeaderLong(uint8_t *buf
) {
218 write32(buf
+ 0, 0xe52de004); // str lr, [sp,#-4]!
219 write32(buf
+ 4, 0xe59fe004); // ldr lr, L2
220 write32(buf
+ 8, 0xe08fe00e); // L1: add lr, pc, lr
221 write32(buf
+ 12, 0xe5bef008); // ldr pc, [lr, #8]
222 write32(buf
+ 16, 0x00000000); // L2: .word &(.got.plt) - L1 - 8
223 write32(buf
+ 20, 0xd4d4d4d4); // Pad to 32-byte boundary
224 write32(buf
+ 24, 0xd4d4d4d4); // Pad to 32-byte boundary
225 write32(buf
+ 28, 0xd4d4d4d4);
226 uint64_t gotPlt
= in
.gotPlt
->getVA();
227 uint64_t l1
= in
.plt
->getVA() + 8;
228 write32(buf
+ 16, gotPlt
- l1
- 8);
231 // The default PLT header requires the .got.plt to be within 128 Mb of the
232 // .plt in the positive direction.
233 void ARM::writePltHeader(uint8_t *buf
) const {
234 // Use a similar sequence to that in writePlt(), the difference is the calling
235 // conventions mean we use lr instead of ip. The PLT entry is responsible for
236 // saving lr on the stack, the dynamic loader is responsible for reloading
238 const uint32_t pltData
[] = {
239 0xe52de004, // L1: str lr, [sp,#-4]!
240 0xe28fe600, // add lr, pc, #0x0NN00000 &(.got.plt - L1 - 4)
241 0xe28eea00, // add lr, lr, #0x000NN000 &(.got.plt - L1 - 4)
242 0xe5bef000, // ldr pc, [lr, #0x00000NNN] &(.got.plt -L1 - 4)
245 uint64_t offset
= in
.gotPlt
->getVA() - in
.plt
->getVA() - 4;
246 if (!llvm::isUInt
<27>(offset
)) {
247 // We cannot encode the Offset, use the long form.
248 writePltHeaderLong(buf
);
251 write32(buf
+ 0, pltData
[0]);
252 write32(buf
+ 4, pltData
[1] | ((offset
>> 20) & 0xff));
253 write32(buf
+ 8, pltData
[2] | ((offset
>> 12) & 0xff));
254 write32(buf
+ 12, pltData
[3] | (offset
& 0xfff));
255 memcpy(buf
+ 16, trapInstr
.data(), 4); // Pad to 32-byte boundary
256 memcpy(buf
+ 20, trapInstr
.data(), 4);
257 memcpy(buf
+ 24, trapInstr
.data(), 4);
258 memcpy(buf
+ 28, trapInstr
.data(), 4);
261 void ARM::addPltHeaderSymbols(InputSection
&isec
) const {
262 addSyntheticLocal("$a", STT_NOTYPE
, 0, 0, isec
);
263 addSyntheticLocal("$d", STT_NOTYPE
, 16, 0, isec
);
266 // Long form PLT entries that do not have any restrictions on the displacement
267 // of the .plt from the .got.plt.
268 static void writePltLong(uint8_t *buf
, uint64_t gotPltEntryAddr
,
269 uint64_t pltEntryAddr
) {
270 write32(buf
+ 0, 0xe59fc004); // ldr ip, L2
271 write32(buf
+ 4, 0xe08cc00f); // L1: add ip, ip, pc
272 write32(buf
+ 8, 0xe59cf000); // ldr pc, [ip]
273 write32(buf
+ 12, 0x00000000); // L2: .word Offset(&(.got.plt) - L1 - 8
274 uint64_t l1
= pltEntryAddr
+ 4;
275 write32(buf
+ 12, gotPltEntryAddr
- l1
- 8);
278 // The default PLT entries require the .got.plt to be within 128 Mb of the
279 // .plt in the positive direction.
280 void ARM::writePlt(uint8_t *buf
, const Symbol
&sym
,
281 uint64_t pltEntryAddr
) const {
282 // The PLT entry is similar to the example given in Appendix A of ELF for
283 // the Arm Architecture. Instead of using the Group Relocations to find the
284 // optimal rotation for the 8-bit immediate used in the add instructions we
285 // hard code the most compact rotations for simplicity. This saves a load
286 // instruction over the long plt sequences.
287 const uint32_t pltData
[] = {
288 0xe28fc600, // L1: add ip, pc, #0x0NN00000 Offset(&(.got.plt) - L1 - 8
289 0xe28cca00, // add ip, ip, #0x000NN000 Offset(&(.got.plt) - L1 - 8
290 0xe5bcf000, // ldr pc, [ip, #0x00000NNN] Offset(&(.got.plt) - L1 - 8
293 uint64_t offset
= sym
.getGotPltVA() - pltEntryAddr
- 8;
294 if (!llvm::isUInt
<27>(offset
)) {
295 // We cannot encode the Offset, use the long form.
296 writePltLong(buf
, sym
.getGotPltVA(), pltEntryAddr
);
299 write32(buf
+ 0, pltData
[0] | ((offset
>> 20) & 0xff));
300 write32(buf
+ 4, pltData
[1] | ((offset
>> 12) & 0xff));
301 write32(buf
+ 8, pltData
[2] | (offset
& 0xfff));
302 memcpy(buf
+ 12, trapInstr
.data(), 4); // Pad to 16-byte boundary
305 void ARM::addPltSymbols(InputSection
&isec
, uint64_t off
) const {
306 addSyntheticLocal("$a", STT_NOTYPE
, off
, 0, isec
);
307 addSyntheticLocal("$d", STT_NOTYPE
, off
+ 12, 0, isec
);
310 bool ARM::needsThunk(RelExpr expr
, RelType type
, const InputFile
*file
,
311 uint64_t branchAddr
, const Symbol
&s
,
313 // If s is an undefined weak symbol and does not have a PLT entry then it will
314 // be resolved as a branch to the next instruction. If it is hidden, its
315 // binding has been converted to local, so we just check isUndefined() here. A
316 // undefined non-weak symbol will have been errored.
317 if (s
.isUndefined() && !s
.isInPlt())
319 // A state change from ARM to Thumb and vice versa must go through an
320 // interworking thunk if the relocation type is not R_ARM_CALL or
326 // Source is ARM, all PLT entries are ARM so no interworking required.
327 // Otherwise we need to interwork if STT_FUNC Symbol has bit 0 set (Thumb).
328 if (s
.isFunc() && expr
== R_PC
&& (s
.getVA() & 1))
332 uint64_t dst
= (expr
== R_PLT_PC
) ? s
.getPltVA() : s
.getVA();
333 return !inBranchRange(type
, branchAddr
, dst
+ a
) ||
334 (!config
->armHasBlx
&& (s
.getVA() & 1));
336 case R_ARM_THM_JUMP19
:
337 case R_ARM_THM_JUMP24
:
338 // Source is Thumb, all PLT entries are ARM so interworking is required.
339 // Otherwise we need to interwork if STT_FUNC Symbol has bit 0 clear (ARM).
340 if (expr
== R_PLT_PC
|| (s
.isFunc() && (s
.getVA() & 1) == 0))
343 case R_ARM_THM_CALL
: {
344 uint64_t dst
= (expr
== R_PLT_PC
) ? s
.getPltVA() : s
.getVA();
345 return !inBranchRange(type
, branchAddr
, dst
+ a
) ||
346 (!config
->armHasBlx
&& (s
.getVA() & 1) == 0);;
352 uint32_t ARM::getThunkSectionSpacing() const {
353 // The placing of pre-created ThunkSections is controlled by the value
354 // thunkSectionSpacing returned by getThunkSectionSpacing(). The aim is to
355 // place the ThunkSection such that all branches from the InputSections
356 // prior to the ThunkSection can reach a Thunk placed at the end of the
357 // ThunkSection. Graphically:
358 // | up to thunkSectionSpacing .text input sections |
360 // | up to thunkSectionSpacing .text input sections |
363 // Pre-created ThunkSections are spaced roughly 16MiB apart on ARMv7. This
364 // is to match the most common expected case of a Thumb 2 encoded BL, BLX or
366 // ARM B, BL, BLX range +/- 32MiB
367 // Thumb B.W, BL, BLX range +/- 16MiB
368 // Thumb B<cc>.W range +/- 1MiB
369 // If a branch cannot reach a pre-created ThunkSection a new one will be
370 // created so we can handle the rare cases of a Thumb 2 conditional branch.
371 // We intentionally use a lower size for thunkSectionSpacing than the maximum
372 // branch range so the end of the ThunkSection is more likely to be within
373 // range of the branch instruction that is furthest away. The value we shorten
374 // thunkSectionSpacing by is set conservatively to allow us to create 16,384
375 // 12 byte Thunks at any offset in a ThunkSection without risk of a branch to
376 // one of the Thunks going out of range.
378 // On Arm the thunkSectionSpacing depends on the range of the Thumb Branch
379 // range. On earlier Architectures such as ARMv4, ARMv5 and ARMv6 (except
380 // ARMv6T2) the range is +/- 4MiB.
382 return (config
->armJ1J2BranchEncoding
) ? 0x1000000 - 0x30000
386 bool ARM::inBranchRange(RelType type
, uint64_t src
, uint64_t dst
) const {
387 if ((dst
& 0x1) == 0)
388 // Destination is ARM, if ARM caller then Src is already 4-byte aligned.
389 // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure
390 // destination will be 4 byte aligned.
393 // Bit 0 == 1 denotes Thumb state, it is not part of the range.
396 int64_t offset
= dst
- src
;
402 return llvm::isInt
<26>(offset
);
403 case R_ARM_THM_JUMP19
:
404 return llvm::isInt
<21>(offset
);
405 case R_ARM_THM_JUMP24
:
407 return config
->armJ1J2BranchEncoding
? llvm::isInt
<25>(offset
)
408 : llvm::isInt
<23>(offset
);
414 // Helper to produce message text when LLD detects that a CALL relocation to
415 // a non STT_FUNC symbol that may result in incorrect interworking between ARM
417 static void stateChangeWarning(uint8_t *loc
, RelType relt
, const Symbol
&s
) {
419 const ErrorPlace place
= getErrorPlace(loc
);
421 if (!place
.srcLoc
.empty())
422 hint
= "; " + place
.srcLoc
;
424 // Section symbols must be defined and in a section. Users cannot change
425 // the type. Use the section name as getName() returns an empty string.
426 warn(place
.loc
+ "branch and link relocation: " + toString(relt
) +
427 " to STT_SECTION symbol " + cast
<Defined
>(s
).section
->name
+
428 " ; interworking not performed" + hint
);
430 // Warn with hint on how to alter the symbol type.
431 warn(getErrorLocation(loc
) + "branch and link relocation: " +
432 toString(relt
) + " to non STT_FUNC symbol: " + s
.getName() +
433 " interworking not performed; consider using directive '.type " +
435 ", %function' to give symbol type STT_FUNC if interworking between "
436 "ARM and Thumb is required" +
441 // Rotate a 32-bit unsigned value right by a specified amt of bits.
442 static uint32_t rotr32(uint32_t val
, uint32_t amt
) {
443 assert(amt
< 32 && "Invalid rotate amount");
444 return (val
>> amt
) | (val
<< ((32 - amt
) & 31));
447 static std::pair
<uint32_t, uint32_t> getRemAndLZForGroup(unsigned group
,
451 lz
= llvm::countl_zero(val
) & ~1;
453 if (lz
== 32) // implies rem == 0
455 val
&= 0xffffff >> lz
;
460 static void encodeAluGroup(uint8_t *loc
, const Relocation
&rel
, uint64_t val
,
461 int group
, bool check
) {
462 // ADD/SUB (immediate) add = bit23, sub = bit22
463 // immediate field carries is a 12-bit modified immediate, made up of a 4-bit
464 // even rotate right and an 8-bit immediate.
465 uint32_t opcode
= 0x00800000;
471 std::tie(imm
, lz
) = getRemAndLZForGroup(group
, val
);
474 imm
= rotr32(imm
, 24 - lz
);
477 if (check
&& imm
> 0xff)
478 error(getErrorLocation(loc
) + "unencodeable immediate " + Twine(val
).str() +
479 " for relocation " + toString(rel
.type
));
480 write32(loc
, (read32(loc
) & 0xff3ff000) | opcode
| rot
| (imm
& 0xff));
483 static void encodeLdrGroup(uint8_t *loc
, const Relocation
&rel
, uint64_t val
,
485 // R_ARM_LDR_PC_Gn is S + A - P, we have ((S + A) | T) - P, if S is a
486 // function then addr is 0 (modulo 2) and Pa is 0 (modulo 4) so we can clear
487 // bottom bit to recover S + A - P.
488 if (rel
.sym
->isFunc())
490 // LDR (literal) u = bit23
491 uint32_t opcode
= 0x00800000;
496 uint32_t imm
= getRemAndLZForGroup(group
, val
).first
;
497 checkUInt(loc
, imm
, 12, rel
);
498 write32(loc
, (read32(loc
) & 0xff7ff000) | opcode
| imm
);
501 static void encodeLdrsGroup(uint8_t *loc
, const Relocation
&rel
, uint64_t val
,
503 // R_ARM_LDRS_PC_Gn is S + A - P, we have ((S + A) | T) - P, if S is a
504 // function then addr is 0 (modulo 2) and Pa is 0 (modulo 4) so we can clear
505 // bottom bit to recover S + A - P.
506 if (rel
.sym
->isFunc())
508 // LDRD/LDRH/LDRSB/LDRSH (literal) u = bit23
509 uint32_t opcode
= 0x00800000;
514 uint32_t imm
= getRemAndLZForGroup(group
, val
).first
;
515 checkUInt(loc
, imm
, 8, rel
);
516 write32(loc
, (read32(loc
) & 0xff7ff0f0) | opcode
| ((imm
& 0xf0) << 4) |
520 void ARM::relocate(uint8_t *loc
, const Relocation
&rel
, uint64_t val
) const {
523 case R_ARM_BASE_PREL
:
534 case R_ARM_TLS_LDM32
:
535 case R_ARM_TLS_LDO32
:
537 case R_ARM_TLS_TPOFF32
:
538 case R_ARM_TLS_DTPOFF32
:
542 checkInt(loc
, val
, 31, rel
);
543 write32(loc
, (read32(loc
) & 0x80000000) | (val
& ~0x80000000));
546 // R_ARM_CALL is used for BL and BLX instructions, for symbols of type
547 // STT_FUNC we choose whether to write a BL or BLX depending on the
548 // value of bit 0 of Val. With bit 0 == 1 denoting Thumb. If the symbol is
549 // not of type STT_FUNC then we must preserve the original instruction.
550 // PLT entries are always ARM state so we know we don't need to interwork.
551 assert(rel
.sym
); // R_ARM_CALL is always reached via relocate().
552 bool bit0Thumb
= val
& 1;
553 bool isBlx
= (read32(loc
) & 0xfe000000) == 0xfa000000;
554 // lld 10.0 and before always used bit0Thumb when deciding to write a BLX
555 // even when type not STT_FUNC.
556 if (!rel
.sym
->isFunc() && isBlx
!= bit0Thumb
)
557 stateChangeWarning(loc
, rel
.type
, *rel
.sym
);
558 if (rel
.sym
->isFunc() ? bit0Thumb
: isBlx
) {
559 // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1'
560 checkInt(loc
, val
, 26, rel
);
561 write32(loc
, 0xfa000000 | // opcode
562 ((val
& 2) << 23) | // H
563 ((val
>> 2) & 0x00ffffff)); // imm24
566 // BLX (always unconditional) instruction to an ARM Target, select an
568 write32(loc
, 0xeb000000 | (read32(loc
) & 0x00ffffff));
569 // fall through as BL encoding is shared with B
575 checkInt(loc
, val
, 26, rel
);
576 write32(loc
, (read32(loc
) & ~0x00ffffff) | ((val
>> 2) & 0x00ffffff));
578 case R_ARM_THM_JUMP8
:
579 // We do a 9 bit check because val is right-shifted by 1 bit.
580 checkInt(loc
, val
, 9, rel
);
581 write16(loc
, (read32(loc
) & 0xff00) | ((val
>> 1) & 0x00ff));
583 case R_ARM_THM_JUMP11
:
584 // We do a 12 bit check because val is right-shifted by 1 bit.
585 checkInt(loc
, val
, 12, rel
);
586 write16(loc
, (read32(loc
) & 0xf800) | ((val
>> 1) & 0x07ff));
588 case R_ARM_THM_JUMP19
:
589 // Encoding T3: Val = S:J2:J1:imm6:imm11:0
590 checkInt(loc
, val
, 21, rel
);
592 (read16(loc
) & 0xfbc0) | // opcode cond
593 ((val
>> 10) & 0x0400) | // S
594 ((val
>> 12) & 0x003f)); // imm6
597 ((val
>> 8) & 0x0800) | // J2
598 ((val
>> 5) & 0x2000) | // J1
599 ((val
>> 1) & 0x07ff)); // imm11
601 case R_ARM_THM_CALL
: {
602 // R_ARM_THM_CALL is used for BL and BLX instructions, for symbols of type
603 // STT_FUNC we choose whether to write a BL or BLX depending on the
604 // value of bit 0 of Val. With bit 0 == 0 denoting ARM, if the symbol is
605 // not of type STT_FUNC then we must preserve the original instruction.
606 // PLT entries are always ARM state so we know we need to interwork.
607 assert(rel
.sym
); // R_ARM_THM_CALL is always reached via relocate().
608 bool bit0Thumb
= val
& 1;
609 bool isBlx
= (read16(loc
+ 2) & 0x1000) == 0;
610 // lld 10.0 and before always used bit0Thumb when deciding to write a BLX
611 // even when type not STT_FUNC. PLT entries generated by LLD are always ARM.
612 if (!rel
.sym
->isFunc() && !rel
.sym
->isInPlt() && isBlx
== bit0Thumb
)
613 stateChangeWarning(loc
, rel
.type
, *rel
.sym
);
614 if (rel
.sym
->isFunc() || rel
.sym
->isInPlt() ? !bit0Thumb
: isBlx
) {
615 // We are writing a BLX. Ensure BLX destination is 4-byte aligned. As
616 // the BLX instruction may only be two byte aligned. This must be done
617 // before overflow check.
618 val
= alignTo(val
, 4);
619 write16(loc
+ 2, read16(loc
+ 2) & ~0x1000);
621 write16(loc
+ 2, (read16(loc
+ 2) & ~0x1000) | 1 << 12);
623 if (!config
->armJ1J2BranchEncoding
) {
624 // Older Arm architectures do not support R_ARM_THM_JUMP24 and have
625 // different encoding rules and range due to J1 and J2 always being 1.
626 checkInt(loc
, val
, 23, rel
);
629 ((val
>> 12) & 0x07ff)); // imm11
631 (read16(loc
+ 2) & 0xd000) | // opcode
632 0x2800 | // J1 == J2 == 1
633 ((val
>> 1) & 0x07ff)); // imm11
637 // Fall through as rest of encoding is the same as B.W
639 case R_ARM_THM_JUMP24
:
640 // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
641 checkInt(loc
, val
, 25, rel
);
644 ((val
>> 14) & 0x0400) | // S
645 ((val
>> 12) & 0x03ff)); // imm10
647 (read16(loc
+ 2) & 0xd000) | // opcode
648 (((~(val
>> 10)) ^ (val
>> 11)) & 0x2000) | // J1
649 (((~(val
>> 11)) ^ (val
>> 13)) & 0x0800) | // J2
650 ((val
>> 1) & 0x07ff)); // imm11
652 case R_ARM_MOVW_ABS_NC
:
653 case R_ARM_MOVW_PREL_NC
:
654 case R_ARM_MOVW_BREL_NC
:
655 write32(loc
, (read32(loc
) & ~0x000f0fff) | ((val
& 0xf000) << 4) |
659 case R_ARM_MOVT_PREL
:
660 case R_ARM_MOVT_BREL
:
661 write32(loc
, (read32(loc
) & ~0x000f0fff) |
662 (((val
>> 16) & 0xf000) << 4) | ((val
>> 16) & 0xfff));
664 case R_ARM_THM_MOVT_ABS
:
665 case R_ARM_THM_MOVT_PREL
:
666 case R_ARM_THM_MOVT_BREL
:
667 // Encoding T1: A = imm4:i:imm3:imm8
671 ((val
>> 17) & 0x0400) | // i
672 ((val
>> 28) & 0x000f)); // imm4
675 (read16(loc
+ 2) & 0x8f00) | // opcode
676 ((val
>> 12) & 0x7000) | // imm3
677 ((val
>> 16) & 0x00ff)); // imm8
679 case R_ARM_THM_MOVW_ABS_NC
:
680 case R_ARM_THM_MOVW_PREL_NC
:
681 case R_ARM_THM_MOVW_BREL_NC
:
682 // Encoding T3: A = imm4:i:imm3:imm8
685 ((val
>> 1) & 0x0400) | // i
686 ((val
>> 12) & 0x000f)); // imm4
688 (read16(loc
+ 2) & 0x8f00) | // opcode
689 ((val
<< 4) & 0x7000) | // imm3
690 (val
& 0x00ff)); // imm8
692 case R_ARM_THM_ALU_ABS_G3
:
693 write16(loc
, (read16(loc
) &~ 0x00ff) | ((val
>> 24) & 0x00ff));
695 case R_ARM_THM_ALU_ABS_G2_NC
:
696 write16(loc
, (read16(loc
) &~ 0x00ff) | ((val
>> 16) & 0x00ff));
698 case R_ARM_THM_ALU_ABS_G1_NC
:
699 write16(loc
, (read16(loc
) &~ 0x00ff) | ((val
>> 8) & 0x00ff));
701 case R_ARM_THM_ALU_ABS_G0_NC
:
702 write16(loc
, (read16(loc
) &~ 0x00ff) | (val
& 0x00ff));
704 case R_ARM_ALU_PC_G0
:
705 encodeAluGroup(loc
, rel
, val
, 0, true);
707 case R_ARM_ALU_PC_G0_NC
:
708 encodeAluGroup(loc
, rel
, val
, 0, false);
710 case R_ARM_ALU_PC_G1
:
711 encodeAluGroup(loc
, rel
, val
, 1, true);
713 case R_ARM_ALU_PC_G1_NC
:
714 encodeAluGroup(loc
, rel
, val
, 1, false);
716 case R_ARM_ALU_PC_G2
:
717 encodeAluGroup(loc
, rel
, val
, 2, true);
719 case R_ARM_LDR_PC_G0
:
720 encodeLdrGroup(loc
, rel
, val
, 0);
722 case R_ARM_LDR_PC_G1
:
723 encodeLdrGroup(loc
, rel
, val
, 1);
725 case R_ARM_LDR_PC_G2
:
726 encodeLdrGroup(loc
, rel
, val
, 2);
728 case R_ARM_LDRS_PC_G0
:
729 encodeLdrsGroup(loc
, rel
, val
, 0);
731 case R_ARM_LDRS_PC_G1
:
732 encodeLdrsGroup(loc
, rel
, val
, 1);
734 case R_ARM_LDRS_PC_G2
:
735 encodeLdrsGroup(loc
, rel
, val
, 2);
737 case R_ARM_THM_ALU_PREL_11_0
: {
738 // ADR encoding T2 (sub), T3 (add) i:imm3:imm8
745 checkUInt(loc
, imm
, 12, rel
);
746 write16(loc
, (read16(loc
) & 0xfb0f) | sub
| (imm
& 0x800) >> 1);
748 (read16(loc
+ 2) & 0x8f00) | (imm
& 0x700) << 4 | (imm
& 0xff));
752 // ADR and LDR literal encoding T1 positive offset only imm8:00
753 // R_ARM_THM_PC8 is S + A - Pa, we have ((S + A) | T) - Pa, if S is a
754 // function then addr is 0 (modulo 2) and Pa is 0 (modulo 4) so we can clear
755 // bottom bit to recover S + A - Pa.
756 if (rel
.sym
->isFunc())
758 checkUInt(loc
, val
, 10, rel
);
759 checkAlignment(loc
, val
, 4, rel
);
760 write16(loc
, (read16(loc
) & 0xff00) | (val
& 0x3fc) >> 2);
762 case R_ARM_THM_PC12
: {
763 // LDR (literal) encoding T2, add = (U == '1') imm12
765 // R_ARM_THM_PC12 is S + A - Pa, we have ((S + A) | T) - Pa, if S is a
766 // function then addr is 0 (modulo 2) and Pa is 0 (modulo 4) so we can clear
767 // bottom bit to recover S + A - Pa.
768 if (rel
.sym
->isFunc())
776 checkUInt(loc
, imm12
, 12, rel
);
777 write16(loc
, read16(loc
) | u
);
778 write16(loc
+ 2, (read16(loc
+ 2) & 0xf000) | imm12
);
782 llvm_unreachable("unknown relocation");
786 int64_t ARM::getImplicitAddend(const uint8_t *buf
, RelType type
) const {
789 internalLinkerError(getErrorLocation(buf
),
790 "cannot read addend for relocation " + toString(type
));
793 case R_ARM_BASE_PREL
:
798 case R_ARM_IRELATIVE
:
804 case R_ARM_TLS_DTPMOD32
:
805 case R_ARM_TLS_DTPOFF32
:
808 case R_ARM_TLS_LDM32
:
810 case R_ARM_TLS_LDO32
:
811 case R_ARM_TLS_TPOFF32
:
812 return SignExtend64
<32>(read32(buf
));
814 return SignExtend64
<31>(read32(buf
));
819 return SignExtend64
<26>(read32(buf
) << 2);
820 case R_ARM_THM_JUMP8
:
821 return SignExtend64
<9>(read16(buf
) << 1);
822 case R_ARM_THM_JUMP11
:
823 return SignExtend64
<12>(read16(buf
) << 1);
824 case R_ARM_THM_JUMP19
: {
825 // Encoding T3: A = S:J2:J1:imm10:imm6:0
826 uint16_t hi
= read16(buf
);
827 uint16_t lo
= read16(buf
+ 2);
828 return SignExtend64
<20>(((hi
& 0x0400) << 10) | // S
829 ((lo
& 0x0800) << 8) | // J2
830 ((lo
& 0x2000) << 5) | // J1
831 ((hi
& 0x003f) << 12) | // imm6
832 ((lo
& 0x07ff) << 1)); // imm11:0
835 if (!config
->armJ1J2BranchEncoding
) {
836 // Older Arm architectures do not support R_ARM_THM_JUMP24 and have
837 // different encoding rules and range due to J1 and J2 always being 1.
838 uint16_t hi
= read16(buf
);
839 uint16_t lo
= read16(buf
+ 2);
840 return SignExtend64
<22>(((hi
& 0x7ff) << 12) | // imm11
841 ((lo
& 0x7ff) << 1)); // imm11:0
845 case R_ARM_THM_JUMP24
: {
846 // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0
847 // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S)
848 uint16_t hi
= read16(buf
);
849 uint16_t lo
= read16(buf
+ 2);
850 return SignExtend64
<24>(((hi
& 0x0400) << 14) | // S
851 (~((lo
^ (hi
<< 3)) << 10) & 0x00800000) | // I1
852 (~((lo
^ (hi
<< 1)) << 11) & 0x00400000) | // I2
853 ((hi
& 0x003ff) << 12) | // imm0
854 ((lo
& 0x007ff) << 1)); // imm11:0
856 // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and
857 // MOVT is in the range -32768 <= A < 32768
858 case R_ARM_MOVW_ABS_NC
:
860 case R_ARM_MOVW_PREL_NC
:
861 case R_ARM_MOVT_PREL
:
862 case R_ARM_MOVW_BREL_NC
:
863 case R_ARM_MOVT_BREL
: {
864 uint64_t val
= read32(buf
) & 0x000f0fff;
865 return SignExtend64
<16>(((val
& 0x000f0000) >> 4) | (val
& 0x00fff));
867 case R_ARM_THM_MOVW_ABS_NC
:
868 case R_ARM_THM_MOVT_ABS
:
869 case R_ARM_THM_MOVW_PREL_NC
:
870 case R_ARM_THM_MOVT_PREL
:
871 case R_ARM_THM_MOVW_BREL_NC
:
872 case R_ARM_THM_MOVT_BREL
: {
873 // Encoding T3: A = imm4:i:imm3:imm8
874 uint16_t hi
= read16(buf
);
875 uint16_t lo
= read16(buf
+ 2);
876 return SignExtend64
<16>(((hi
& 0x000f) << 12) | // imm4
877 ((hi
& 0x0400) << 1) | // i
878 ((lo
& 0x7000) >> 4) | // imm3
879 (lo
& 0x00ff)); // imm8
881 case R_ARM_THM_ALU_ABS_G0_NC
:
882 case R_ARM_THM_ALU_ABS_G1_NC
:
883 case R_ARM_THM_ALU_ABS_G2_NC
:
884 case R_ARM_THM_ALU_ABS_G3
:
885 return read16(buf
) & 0xff;
886 case R_ARM_ALU_PC_G0
:
887 case R_ARM_ALU_PC_G0_NC
:
888 case R_ARM_ALU_PC_G1
:
889 case R_ARM_ALU_PC_G1_NC
:
890 case R_ARM_ALU_PC_G2
: {
891 // 12-bit immediate is a modified immediate made up of a 4-bit even
892 // right rotation and 8-bit constant. After the rotation the value
893 // is zero-extended. When bit 23 is set the instruction is an add, when
894 // bit 22 is set it is a sub.
895 uint32_t instr
= read32(buf
);
896 uint32_t val
= rotr32(instr
& 0xff, ((instr
& 0xf00) >> 8) * 2);
897 return (instr
& 0x00400000) ? -val
: val
;
899 case R_ARM_LDR_PC_G0
:
900 case R_ARM_LDR_PC_G1
:
901 case R_ARM_LDR_PC_G2
: {
902 // ADR (literal) add = bit23, sub = bit22
903 // LDR (literal) u = bit23 unsigned imm12
904 bool u
= read32(buf
) & 0x00800000;
905 uint32_t imm12
= read32(buf
) & 0xfff;
906 return u
? imm12
: -imm12
;
908 case R_ARM_LDRS_PC_G0
:
909 case R_ARM_LDRS_PC_G1
:
910 case R_ARM_LDRS_PC_G2
: {
911 // LDRD/LDRH/LDRSB/LDRSH (literal) u = bit23 unsigned imm8
912 uint32_t opcode
= read32(buf
);
913 bool u
= opcode
& 0x00800000;
914 uint32_t imm4l
= opcode
& 0xf;
915 uint32_t imm4h
= (opcode
& 0xf00) >> 4;
916 return u
? (imm4h
| imm4l
) : -(imm4h
| imm4l
);
918 case R_ARM_THM_ALU_PREL_11_0
: {
919 // Thumb2 ADR, which is an alias for a sub or add instruction with an
920 // unsigned immediate.
921 // ADR encoding T2 (sub), T3 (add) i:imm3:imm8
922 uint16_t hi
= read16(buf
);
923 uint16_t lo
= read16(buf
+ 2);
924 uint64_t imm
= (hi
& 0x0400) << 1 | // i
925 (lo
& 0x7000) >> 4 | // imm3
926 (lo
& 0x00ff); // imm8
927 // For sub, addend is negative, add is positive.
928 return (hi
& 0x00f0) ? -imm
: imm
;
931 // ADR and LDR (literal) encoding T1
932 // From ELF for the ARM Architecture the initial signed addend is formed
933 // from an unsigned field using expression (((imm8:00 + 4) & 0x3ff) ā 4)
934 // this trick permits the PC bias of -4 to be encoded using imm8 = 0xff
935 return ((((read16(buf
) & 0xff) << 2) + 4) & 0x3ff) - 4;
936 case R_ARM_THM_PC12
: {
937 // LDR (literal) encoding T2, add = (U == '1') imm12
938 bool u
= read16(buf
) & 0x0080;
939 uint64_t imm12
= read16(buf
+ 2) & 0x0fff;
940 return u
? imm12
: -imm12
;
944 case R_ARM_JUMP_SLOT
:
945 // These relocations are defined as not having an implicit addend.
950 static bool isArmMapSymbol(const Symbol
*b
) {
951 return b
->getName() == "$a" || b
->getName().startswith("$a.");
954 static bool isThumbMapSymbol(const Symbol
*s
) {
955 return s
->getName() == "$t" || s
->getName().startswith("$t.");
958 static bool isDataMapSymbol(const Symbol
*b
) {
959 return b
->getName() == "$d" || b
->getName().startswith("$d.");
962 void elf::sortArmMappingSymbols() {
963 // For each input section make sure the mapping symbols are sorted in
965 for (auto &kv
: sectionMap
) {
966 SmallVector
<const Defined
*, 0> &mapSyms
= kv
.second
;
967 llvm::stable_sort(mapSyms
, [](const Defined
*a
, const Defined
*b
) {
968 return a
->value
< b
->value
;
973 void elf::addArmInputSectionMappingSymbols() {
974 // Collect mapping symbols for every executable input sections.
975 // The linker generated mapping symbols for all the synthetic
976 // sections are adding into the sectionmap through the function
977 // addArmSyntheitcSectionMappingSymbol.
978 for (ELFFileBase
*file
: ctx
.objectFiles
) {
979 for (Symbol
*sym
: file
->getLocalSymbols()) {
980 auto *def
= dyn_cast
<Defined
>(sym
);
983 if (!isArmMapSymbol(def
) && !isDataMapSymbol(def
) &&
984 !isThumbMapSymbol(def
))
986 if (auto *sec
= cast_if_present
<InputSection
>(def
->section
))
987 if (sec
->flags
& SHF_EXECINSTR
)
988 sectionMap
[sec
].push_back(def
);
993 // Synthetic sections are not backed by an ELF file where we can access the
994 // symbol table, instead mapping symbols added to synthetic sections are stored
995 // in the synthetic symbol table. Due to the presence of strip (--strip-all),
996 // we can not rely on the synthetic symbol table retaining the mapping symbols.
997 // Instead we record the mapping symbols locally.
998 void elf::addArmSyntheticSectionMappingSymbol(Defined
*sym
) {
999 if (!isArmMapSymbol(sym
) && !isDataMapSymbol(sym
) && !isThumbMapSymbol(sym
))
1001 if (auto *sec
= cast_if_present
<InputSection
>(sym
->section
))
1002 if (sec
->flags
& SHF_EXECINSTR
)
1003 sectionMap
[sec
].push_back(sym
);
1006 static void toLittleEndianInstructions(uint8_t *buf
, uint64_t start
,
1007 uint64_t end
, uint64_t width
) {
1008 CodeState curState
= static_cast<CodeState
>(width
);
1009 if (curState
== CodeState::Arm
)
1010 for (uint64_t i
= start
; i
< end
; i
+= width
)
1011 write32le(buf
+ i
, read32(buf
+ i
));
1013 if (curState
== CodeState::Thumb
)
1014 for (uint64_t i
= start
; i
< end
; i
+= width
)
1015 write16le(buf
+ i
, read16(buf
+ i
));
1018 // Arm BE8 big endian format requires instructions to be little endian, with
1019 // the initial contents big-endian. Convert the big-endian instructions to
1020 // little endian leaving literal data untouched. We use mapping symbols to
1021 // identify half open intervals of Arm code [$a, non $a) and Thumb code
1022 // [$t, non $t) and convert these to little endian a word or half word at a
1023 // time respectively.
1024 void elf::convertArmInstructionstoBE8(InputSection
*sec
, uint8_t *buf
) {
1025 if (!sectionMap
.contains(sec
))
1028 SmallVector
<const Defined
*, 0> &mapSyms
= sectionMap
[sec
];
1030 if (mapSyms
.empty())
1033 CodeState curState
= CodeState::Data
;
1034 uint64_t start
= 0, width
= 0, size
= sec
->getSize();
1035 for (auto &msym
: mapSyms
) {
1036 CodeState newState
= CodeState::Data
;
1037 if (isThumbMapSymbol(msym
))
1038 newState
= CodeState::Thumb
;
1039 else if (isArmMapSymbol(msym
))
1040 newState
= CodeState::Arm
;
1042 if (newState
== curState
)
1045 if (curState
!= CodeState::Data
) {
1046 width
= static_cast<uint64_t>(curState
);
1047 toLittleEndianInstructions(buf
, start
, msym
->value
, width
);
1049 start
= msym
->value
;
1050 curState
= newState
;
1053 // Passed last mapping symbol, may need to reverse
1054 // up to end of section.
1055 if (curState
!= CodeState::Data
) {
1056 width
= static_cast<uint64_t>(curState
);
1057 toLittleEndianInstructions(buf
, start
, size
, width
);
1061 // The Arm Cortex-M Security Extensions (CMSE) splits a system into two parts;
1062 // the non-secure and secure states with the secure state inaccessible from the
1063 // non-secure state, apart from an area of memory in secure state called the
1064 // secure gateway which is accessible from non-secure state. The secure gateway
1065 // contains one or more entry points which must start with a landing pad
1066 // instruction SG. Arm recommends that the secure gateway consists only of
1067 // secure gateway veneers, which are made up of a SG instruction followed by a
1068 // branch to the destination in secure state. Full details can be found in Arm
1069 // v8-M Security Extensions Requirements on Development Tools.
1071 // The CMSE model of software development requires the non-secure and secure
1072 // states to be developed as two separate programs. The non-secure developer is
1073 // provided with an import library defining symbols describing the entry points
1074 // in the secure gateway. No additional linker support is required for the
1075 // non-secure state.
1077 // Development of the secure state requires linker support to manage the secure
1078 // gateway veneers. The management consists of:
1079 // - Creation of new secure gateway veneers based on symbol conventions.
1080 // - Checking the address of existing secure gateway veneers.
1081 // - Warning when existing secure gateway veneers removed.
1083 // The secure gateway veneers are created in an import library, which is just an
1084 // ELF object with a symbol table. The import library is controlled by two
1085 // command line options:
1086 // --in-implib (specify an input import library from a previous revision of the
1088 // --out-implib (specify an output import library to be created by the linker).
1090 // The input import library is used to manage consistency of the secure entry
1091 // points. The output import library is for new and updated secure entry points.
1093 // The symbol convention that identifies secure entry functions is the prefix
1094 // __acle_se_ for a symbol called name the linker is expected to create a secure
1095 // gateway veneer if symbols __acle_se_name and name have the same address.
1096 // After creating a secure gateway veneer the symbol name labels the secure
1097 // gateway veneer and the __acle_se_name labels the function definition.
1099 // The LLD implementation:
1100 // - Reads an existing import library with importCmseSymbols().
1101 // - Determines which new secure gateway veneers to create and redirects calls
1102 // within the secure state to the __acle_se_ prefixed symbol with
1103 // processArmCmseSymbols().
1104 // - Models the SG veneers as a synthetic section.
1106 // Initialize symbols. symbols is a parallel array to the corresponding ELF
1108 template <class ELFT
> void ObjFile
<ELFT
>::importCmseSymbols() {
1109 ArrayRef
<Elf_Sym
> eSyms
= getELFSyms
<ELFT
>();
1110 // Error for local symbols. The symbol at index 0 is LOCAL. So skip it.
1111 for (size_t i
= 1, end
= firstGlobal
; i
!= end
; ++i
) {
1112 errorOrWarn("CMSE symbol '" + CHECK(eSyms
[i
].getName(stringTable
), this) +
1113 "' in import library '" + toString(this) + "' is not global");
1116 for (size_t i
= firstGlobal
, end
= eSyms
.size(); i
!= end
; ++i
) {
1117 const Elf_Sym
&eSym
= eSyms
[i
];
1118 Defined
*sym
= reinterpret_cast<Defined
*>(make
<SymbolUnion
>());
1120 // Initialize symbol fields.
1121 memset(sym
, 0, sizeof(Symbol
));
1122 sym
->setName(CHECK(eSyms
[i
].getName(stringTable
), this));
1123 sym
->value
= eSym
.st_value
;
1124 sym
->size
= eSym
.st_size
;
1125 sym
->type
= eSym
.getType();
1126 sym
->binding
= eSym
.getBinding();
1127 sym
->stOther
= eSym
.st_other
;
1129 if (eSym
.st_shndx
!= SHN_ABS
) {
1130 error("CMSE symbol '" + sym
->getName() + "' in import library '" +
1131 toString(this) + "' is not absolute");
1135 if (!(eSym
.st_value
& 1) || (eSym
.getType() != STT_FUNC
)) {
1136 error("CMSE symbol '" + sym
->getName() + "' in import library '" +
1137 toString(this) + "' is not a Thumb function definition");
1141 if (symtab
.cmseImportLib
.count(sym
->getName())) {
1142 error("CMSE symbol '" + sym
->getName() +
1143 "' is multiply defined in import library '" + toString(this) + "'");
1147 if (eSym
.st_size
!= ACLESESYM_SIZE
) {
1148 warn("CMSE symbol '" + sym
->getName() + "' in import library '" +
1149 toString(this) + "' does not have correct size of " +
1150 Twine(ACLESESYM_SIZE
) + " bytes");
1153 symtab
.cmseImportLib
[sym
->getName()] = sym
;
1157 // Check symbol attributes of the acleSeSym, sym pair.
1158 // Both symbols should be global/weak Thumb code symbol definitions.
1159 static std::string
checkCmseSymAttributes(Symbol
*acleSeSym
, Symbol
*sym
) {
1160 auto check
= [](Symbol
*s
, StringRef type
) -> std::optional
<std::string
> {
1161 auto d
= dyn_cast_or_null
<Defined
>(s
);
1162 if (!(d
&& d
->isFunc() && (d
->value
& 1)))
1163 return (Twine(toString(s
->file
)) + ": cmse " + type
+ " symbol '" +
1164 s
->getName() + "' is not a Thumb function definition")
1167 return (Twine(toString(s
->file
)) + ": cmse " + type
+ " symbol '" +
1168 s
->getName() + "' cannot be an absolute symbol")
1170 return std::nullopt
;
1172 for (auto [sym
, type
] :
1173 {std::make_pair(acleSeSym
, "special"), std::make_pair(sym
, "entry")})
1174 if (auto err
= check(sym
, type
))
1179 // Look for [__acle_se_<sym>, <sym>] pairs, as specified in the Cortex-M
1180 // Security Extensions specification.
1181 // 1) <sym> : A standard function name.
1182 // 2) __acle_se_<sym> : A special symbol that prefixes the standard function
1183 // name with __acle_se_.
1184 // Both these symbols are Thumb function symbols with external linkage.
1185 // <sym> may be redefined in .gnu.sgstubs.
1186 void elf::processArmCmseSymbols() {
1187 if (!config
->cmseImplib
)
1189 // Only symbols with external linkage end up in symtab, so no need to do
1190 // linkage checks. Only check symbol type.
1191 for (Symbol
*acleSeSym
: symtab
.getSymbols()) {
1192 if (!acleSeSym
->getName().startswith(ACLESESYM_PREFIX
))
1194 // If input object build attributes do not support CMSE, error and disable
1195 // further scanning for <sym>, __acle_se_<sym> pairs.
1196 if (!config
->armCMSESupport
) {
1197 error("CMSE is only supported by ARMv8-M architecture or later");
1198 config
->cmseImplib
= false;
1202 // Try to find the associated symbol definition.
1203 // Symbol must have external linkage.
1204 StringRef name
= acleSeSym
->getName().substr(std::strlen(ACLESESYM_PREFIX
));
1205 Symbol
*sym
= symtab
.find(name
);
1207 error(toString(acleSeSym
->file
) + ": cmse special symbol '" +
1208 acleSeSym
->getName() +
1209 "' detected, but no associated entry function definition '" + name
+
1210 "' with external linkage found");
1214 std::string errMsg
= checkCmseSymAttributes(acleSeSym
, sym
);
1215 if (!errMsg
.empty()) {
1220 // <sym> may be redefined later in the link in .gnu.sgstubs
1221 symtab
.cmseSymMap
[name
] = {acleSeSym
, sym
};
1224 // If this is an Arm CMSE secure app, replace references to entry symbol <sym>
1225 // with its corresponding special symbol __acle_se_<sym>.
1226 parallelForEach(ctx
.objectFiles
, [&](InputFile
*file
) {
1227 MutableArrayRef
<Symbol
*> syms
= file
->getMutableSymbols();
1228 for (size_t i
= 0, e
= syms
.size(); i
!= e
; ++i
) {
1229 StringRef symName
= syms
[i
]->getName();
1230 if (symtab
.cmseSymMap
.count(symName
))
1231 syms
[i
] = symtab
.cmseSymMap
[symName
].acleSeSym
;
1236 class elf::ArmCmseSGVeneer
{
1238 ArmCmseSGVeneer(Symbol
*sym
, Symbol
*acleSeSym
,
1239 std::optional
<uint64_t> addr
= std::nullopt
)
1240 : sym(sym
), acleSeSym(acleSeSym
), entAddr
{addr
} {}
1241 static const size_t size
{ACLESESYM_SIZE
};
1242 const std::optional
<uint64_t> getAddr() const { return entAddr
; };
1246 uint64_t offset
= 0;
1249 const std::optional
<uint64_t> entAddr
;
1252 ArmCmseSGSection::ArmCmseSGSection()
1253 : SyntheticSection(llvm::ELF::SHF_ALLOC
| llvm::ELF::SHF_EXECINSTR
,
1254 llvm::ELF::SHT_PROGBITS
,
1255 /*alignment=*/32, ".gnu.sgstubs") {
1256 entsize
= ACLESESYM_SIZE
;
1257 // The range of addresses used in the CMSE import library should be fixed.
1258 for (auto &[_
, sym
] : symtab
.cmseImportLib
) {
1259 if (impLibMaxAddr
<= sym
->value
)
1260 impLibMaxAddr
= sym
->value
+ sym
->size
;
1262 if (symtab
.cmseSymMap
.empty())
1265 for (auto &[_
, entryFunc
] : symtab
.cmseSymMap
)
1266 addSGVeneer(cast
<Defined
>(entryFunc
.acleSeSym
),
1267 cast
<Defined
>(entryFunc
.sym
));
1268 for (auto &[_
, sym
] : symtab
.cmseImportLib
) {
1269 if (!symtab
.inCMSEOutImpLib
.count(sym
->getName()))
1270 warn("entry function '" + sym
->getName() +
1271 "' from CMSE import library is not present in secure application");
1274 if (!symtab
.cmseImportLib
.empty() && config
->cmseOutputLib
.empty()) {
1275 for (auto &[_
, entryFunc
] : symtab
.cmseSymMap
) {
1276 Symbol
*sym
= entryFunc
.sym
;
1277 if (!symtab
.inCMSEOutImpLib
.count(sym
->getName()))
1278 warn("new entry function '" + sym
->getName() +
1279 "' introduced but no output import library specified");
1284 void ArmCmseSGSection::addSGVeneer(Symbol
*acleSeSym
, Symbol
*sym
) {
1285 entries
.emplace_back(acleSeSym
, sym
);
1286 if (symtab
.cmseImportLib
.count(sym
->getName()))
1287 symtab
.inCMSEOutImpLib
[sym
->getName()] = true;
1288 // Symbol addresses different, nothing to do.
1289 if (acleSeSym
->file
!= sym
->file
||
1290 cast
<Defined
>(*acleSeSym
).value
!= cast
<Defined
>(*sym
).value
)
1292 // Only secure symbols with values equal to that of it's non-secure
1293 // counterpart needs to be in the .gnu.sgstubs section.
1294 ArmCmseSGVeneer
*ss
= nullptr;
1295 if (symtab
.cmseImportLib
.count(sym
->getName())) {
1296 Defined
*impSym
= symtab
.cmseImportLib
[sym
->getName()];
1297 ss
= make
<ArmCmseSGVeneer
>(sym
, acleSeSym
, impSym
->value
);
1299 ss
= make
<ArmCmseSGVeneer
>(sym
, acleSeSym
);
1302 sgVeneers
.emplace_back(ss
);
1305 void ArmCmseSGSection::writeTo(uint8_t *buf
) {
1306 for (ArmCmseSGVeneer
*s
: sgVeneers
) {
1307 uint8_t *p
= buf
+ s
->offset
;
1308 write16(p
+ 0, 0xe97f); // SG
1309 write16(p
+ 2, 0xe97f);
1310 write16(p
+ 4, 0xf000); // B.W S
1311 write16(p
+ 6, 0xb000);
1312 target
->relocateNoSym(p
+ 4, R_ARM_THM_JUMP24
,
1313 s
->acleSeSym
->getVA() -
1314 (getVA() + s
->offset
+ s
->size
));
1318 void ArmCmseSGSection::addMappingSymbol() {
1319 addSyntheticLocal("$t", STT_NOTYPE
, /*off=*/0, /*size=*/0, *this);
1322 size_t ArmCmseSGSection::getSize() const {
1323 if (sgVeneers
.empty())
1324 return (impLibMaxAddr
? impLibMaxAddr
- getVA() : 0) + newEntries
* entsize
;
1326 return entries
.size() * entsize
;
1329 void ArmCmseSGSection::finalizeContents() {
1330 if (sgVeneers
.empty())
1334 std::stable_partition(sgVeneers
.begin(), sgVeneers
.end(),
1335 [](auto *i
) { return i
->getAddr().has_value(); });
1336 std::sort(sgVeneers
.begin(), it
, [](auto *a
, auto *b
) {
1337 return a
->getAddr().value() < b
->getAddr().value();
1339 // This is the partition of the veneers with fixed addresses.
1340 uint64_t addr
= (*sgVeneers
.begin())->getAddr().has_value()
1341 ? (*sgVeneers
.begin())->getAddr().value()
1343 // Check if the start address of '.gnu.sgstubs' correspond to the
1344 // linker-synthesized veneer with the lowest address.
1345 if ((getVA() & ~1) != (addr
& ~1)) {
1346 error("start address of '.gnu.sgstubs' is different from previous link");
1350 for (size_t i
= 0; i
< sgVeneers
.size(); ++i
) {
1351 ArmCmseSGVeneer
*s
= sgVeneers
[i
];
1352 s
->offset
= i
* s
->size
;
1353 Defined(file
, StringRef(), s
->sym
->binding
, s
->sym
->stOther
, s
->sym
->type
,
1354 s
->offset
| 1, s
->size
, this)
1355 .overwrite(*s
->sym
);
1359 // Write the CMSE import library to disk.
1360 // The CMSE import library is a relocatable object with only a symbol table.
1361 // The symbols are copies of the (absolute) symbols of the secure gateways
1362 // in the executable output by this link.
1363 // See ArmĀ® v8-M Security Extensions: Requirements on Development Tools
1364 // https://developer.arm.com/documentation/ecm0359818/latest
1365 template <typename ELFT
> void elf::writeARMCmseImportLib() {
1366 StringTableSection
*shstrtab
=
1367 make
<StringTableSection
>(".shstrtab", /*dynamic=*/false);
1368 StringTableSection
*strtab
=
1369 make
<StringTableSection
>(".strtab", /*dynamic=*/false);
1370 SymbolTableBaseSection
*impSymTab
= make
<SymbolTableSection
<ELFT
>>(*strtab
);
1372 SmallVector
<std::pair
<OutputSection
*, SyntheticSection
*>, 0> osIsPairs
;
1373 osIsPairs
.emplace_back(make
<OutputSection
>(strtab
->name
, 0, 0), strtab
);
1374 osIsPairs
.emplace_back(make
<OutputSection
>(impSymTab
->name
, 0, 0), impSymTab
);
1375 osIsPairs
.emplace_back(make
<OutputSection
>(shstrtab
->name
, 0, 0), shstrtab
);
1377 std::sort(symtab
.cmseSymMap
.begin(), symtab
.cmseSymMap
.end(),
1378 [](const auto &a
, const auto &b
) -> bool {
1379 return a
.second
.sym
->getVA() < b
.second
.sym
->getVA();
1381 // Copy the secure gateway entry symbols to the import library symbol table.
1382 for (auto &p
: symtab
.cmseSymMap
) {
1383 Defined
*d
= cast
<Defined
>(p
.second
.sym
);
1384 impSymTab
->addSymbol(makeDefined(nullptr, d
->getName(), d
->computeBinding(),
1385 /*stOther=*/0, STT_FUNC
, d
->getVA(),
1386 d
->getSize(), nullptr));
1390 uint64_t off
= sizeof(typename
ELFT::Ehdr
);
1391 for (auto &[osec
, isec
] : osIsPairs
) {
1392 osec
->sectionIndex
= ++idx
;
1393 osec
->recordSection(isec
);
1394 osec
->finalizeInputSections();
1395 osec
->shName
= shstrtab
->addString(osec
->name
);
1396 osec
->size
= isec
->getSize();
1397 isec
->finalizeContents();
1398 osec
->offset
= alignToPowerOf2(off
, osec
->addralign
);
1399 off
= osec
->offset
+ osec
->size
;
1402 const uint64_t sectionHeaderOff
= alignToPowerOf2(off
, config
->wordsize
);
1403 const auto shnum
= osIsPairs
.size() + 1;
1404 const uint64_t fileSize
=
1405 sectionHeaderOff
+ shnum
* sizeof(typename
ELFT::Shdr
);
1406 const unsigned flags
=
1407 config
->mmapOutputFile
? 0 : (unsigned)FileOutputBuffer::F_no_mmap
;
1408 unlinkAsync(config
->cmseOutputLib
);
1409 Expected
<std::unique_ptr
<FileOutputBuffer
>> bufferOrErr
=
1410 FileOutputBuffer::create(config
->cmseOutputLib
, fileSize
, flags
);
1412 error("failed to open " + config
->cmseOutputLib
+ ": " +
1413 llvm::toString(bufferOrErr
.takeError()));
1417 // Write the ELF Header
1418 std::unique_ptr
<FileOutputBuffer
> &buffer
= *bufferOrErr
;
1419 uint8_t *const buf
= buffer
->getBufferStart();
1420 memcpy(buf
, "\177ELF", 4);
1421 auto *eHdr
= reinterpret_cast<typename
ELFT::Ehdr
*>(buf
);
1422 eHdr
->e_type
= ET_REL
;
1424 eHdr
->e_shoff
= sectionHeaderOff
;
1425 eHdr
->e_ident
[EI_CLASS
] = ELFCLASS32
;
1426 eHdr
->e_ident
[EI_DATA
] = config
->isLE
? ELFDATA2LSB
: ELFDATA2MSB
;
1427 eHdr
->e_ident
[EI_VERSION
] = EV_CURRENT
;
1428 eHdr
->e_ident
[EI_OSABI
] = config
->osabi
;
1429 eHdr
->e_ident
[EI_ABIVERSION
] = 0;
1430 eHdr
->e_machine
= EM_ARM
;
1431 eHdr
->e_version
= EV_CURRENT
;
1432 eHdr
->e_flags
= config
->eflags
;
1433 eHdr
->e_ehsize
= sizeof(typename
ELFT::Ehdr
);
1435 eHdr
->e_shentsize
= sizeof(typename
ELFT::Shdr
);
1437 eHdr
->e_phentsize
= 0;
1438 eHdr
->e_shnum
= shnum
;
1439 eHdr
->e_shstrndx
= shstrtab
->getParent()->sectionIndex
;
1441 // Write the section header table.
1442 auto *sHdrs
= reinterpret_cast<typename
ELFT::Shdr
*>(buf
+ eHdr
->e_shoff
);
1443 for (auto &[osec
, _
] : osIsPairs
)
1444 osec
->template writeHeaderTo
<ELFT
>(++sHdrs
);
1446 // Write section contents to a mmap'ed file.
1448 parallel::TaskGroup tg
;
1449 for (auto &[osec
, _
] : osIsPairs
)
1450 osec
->template writeTo
<ELFT
>(buf
+ osec
->offset
, tg
);
1453 if (auto e
= buffer
->commit())
1454 fatal("failed to write output '" + buffer
->getPath() +
1455 "': " + toString(std::move(e
)));
1458 TargetInfo
*elf::getARMTargetInfo() {
1463 template void elf::writeARMCmseImportLib
<ELF32LE
>();
1464 template void elf::writeARMCmseImportLib
<ELF32BE
>();
1465 template void elf::writeARMCmseImportLib
<ELF64LE
>();
1466 template void elf::writeARMCmseImportLib
<ELF64BE
>();
1468 template void ObjFile
<ELF32LE
>::importCmseSymbols();
1469 template void ObjFile
<ELF32BE
>::importCmseSymbols();
1470 template void ObjFile
<ELF64LE
>::importCmseSymbols();
1471 template void ObjFile
<ELF64BE
>::importCmseSymbols();