Skip to content

Commit 78eabca

Browse files
committed
[libunwind] Add support for PC reg column in arm64
This change adds support for the dwarf PC register column in arm64, allowing CFI directives to make use of it. As of the last revision of the DWARF for ARM 64-bit architecture[0], the pc register has been added as a valir register, with number 32. This allows libunwinder to restore both pc and lr, which is useful for stack switches and signal contexts. [0]: https://github.com/ARM-software/abi-aa/blob/f52e1ad3f81254497a83578dc102f6aac89e52d0/aadwarf64/aadwarf64.rst Reviewed By: phosek, #libunwind Differential Revision: https://reviews.llvm.org/D96901
1 parent 2628e91 commit 78eabca

File tree

2 files changed

+44
-33
lines changed

2 files changed

+44
-33
lines changed

libunwind/include/libunwind.h

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -493,16 +493,16 @@ enum {
493493

494494
// 64-bit ARM64 registers
495495
enum {
496-
UNW_ARM64_X0 = 0,
497-
UNW_ARM64_X1 = 1,
498-
UNW_ARM64_X2 = 2,
499-
UNW_ARM64_X3 = 3,
500-
UNW_ARM64_X4 = 4,
501-
UNW_ARM64_X5 = 5,
502-
UNW_ARM64_X6 = 6,
503-
UNW_ARM64_X7 = 7,
504-
UNW_ARM64_X8 = 8,
505-
UNW_ARM64_X9 = 9,
496+
UNW_ARM64_X0 = 0,
497+
UNW_ARM64_X1 = 1,
498+
UNW_ARM64_X2 = 2,
499+
UNW_ARM64_X3 = 3,
500+
UNW_ARM64_X4 = 4,
501+
UNW_ARM64_X5 = 5,
502+
UNW_ARM64_X6 = 6,
503+
UNW_ARM64_X7 = 7,
504+
UNW_ARM64_X8 = 8,
505+
UNW_ARM64_X9 = 9,
506506
UNW_ARM64_X10 = 10,
507507
UNW_ARM64_X11 = 11,
508508
UNW_ARM64_X12 = 12,
@@ -523,24 +523,25 @@ enum {
523523
UNW_ARM64_X27 = 27,
524524
UNW_ARM64_X28 = 28,
525525
UNW_ARM64_X29 = 29,
526-
UNW_ARM64_FP = 29,
526+
UNW_ARM64_FP = 29,
527527
UNW_ARM64_X30 = 30,
528-
UNW_ARM64_LR = 30,
528+
UNW_ARM64_LR = 30,
529529
UNW_ARM64_X31 = 31,
530-
UNW_ARM64_SP = 31,
530+
UNW_ARM64_SP = 31,
531+
UNW_ARM64_PC = 32,
531532
// reserved block
532533
UNW_ARM64_RA_SIGN_STATE = 34,
533534
// reserved block
534-
UNW_ARM64_D0 = 64,
535-
UNW_ARM64_D1 = 65,
536-
UNW_ARM64_D2 = 66,
537-
UNW_ARM64_D3 = 67,
538-
UNW_ARM64_D4 = 68,
539-
UNW_ARM64_D5 = 69,
540-
UNW_ARM64_D6 = 70,
541-
UNW_ARM64_D7 = 71,
542-
UNW_ARM64_D8 = 72,
543-
UNW_ARM64_D9 = 73,
535+
UNW_ARM64_D0 = 64,
536+
UNW_ARM64_D1 = 65,
537+
UNW_ARM64_D2 = 66,
538+
UNW_ARM64_D3 = 67,
539+
UNW_ARM64_D4 = 68,
540+
UNW_ARM64_D5 = 69,
541+
UNW_ARM64_D6 = 70,
542+
UNW_ARM64_D7 = 71,
543+
UNW_ARM64_D8 = 72,
544+
UNW_ARM64_D9 = 73,
544545
UNW_ARM64_D10 = 74,
545546
UNW_ARM64_D11 = 75,
546547
UNW_ARM64_D12 = 76,

libunwind/src/Registers.hpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,31 +1849,39 @@ inline bool Registers_arm64::validRegister(int regNum) const {
18491849
return false;
18501850
if (regNum == UNW_ARM64_RA_SIGN_STATE)
18511851
return true;
1852-
if ((regNum > 31) && (regNum < 64))
1852+
if ((regNum > 32) && (regNum < 64))
18531853
return false;
18541854
return true;
18551855
}
18561856

18571857
inline uint64_t Registers_arm64::getRegister(int regNum) const {
1858-
if (regNum == UNW_REG_IP)
1858+
if (regNum == UNW_REG_IP || regNum == UNW_ARM64_PC)
18591859
return _registers.__pc;
1860-
if (regNum == UNW_REG_SP)
1860+
if (regNum == UNW_REG_SP || regNum == UNW_ARM64_SP)
18611861
return _registers.__sp;
18621862
if (regNum == UNW_ARM64_RA_SIGN_STATE)
18631863
return _registers.__ra_sign_state;
1864-
if ((regNum >= 0) && (regNum < 32))
1864+
if (regNum == UNW_ARM64_FP)
1865+
return _registers.__fp;
1866+
if (regNum == UNW_ARM64_LR)
1867+
return _registers.__lr;
1868+
if ((regNum >= 0) && (regNum < 29))
18651869
return _registers.__x[regNum];
18661870
_LIBUNWIND_ABORT("unsupported arm64 register");
18671871
}
18681872

18691873
inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1870-
if (regNum == UNW_REG_IP)
1874+
if (regNum == UNW_REG_IP || regNum == UNW_ARM64_PC)
18711875
_registers.__pc = value;
1872-
else if (regNum == UNW_REG_SP)
1876+
else if (regNum == UNW_REG_SP || regNum == UNW_ARM64_SP)
18731877
_registers.__sp = value;
18741878
else if (regNum == UNW_ARM64_RA_SIGN_STATE)
18751879
_registers.__ra_sign_state = value;
1876-
else if ((regNum >= 0) && (regNum < 32))
1880+
else if (regNum == UNW_ARM64_FP)
1881+
_registers.__fp = value;
1882+
else if (regNum == UNW_ARM64_LR)
1883+
_registers.__lr = value;
1884+
else if ((regNum >= 0) && (regNum < 29))
18771885
_registers.__x[regNum] = value;
18781886
else
18791887
_LIBUNWIND_ABORT("unsupported arm64 register");
@@ -1943,12 +1951,14 @@ inline const char *Registers_arm64::getRegisterName(int regNum) {
19431951
return "x27";
19441952
case UNW_ARM64_X28:
19451953
return "x28";
1946-
case UNW_ARM64_X29:
1954+
case UNW_ARM64_FP:
19471955
return "fp";
1948-
case UNW_ARM64_X30:
1956+
case UNW_ARM64_LR:
19491957
return "lr";
1950-
case UNW_ARM64_X31:
1958+
case UNW_ARM64_SP:
19511959
return "sp";
1960+
case UNW_ARM64_PC:
1961+
return "pc";
19521962
case UNW_ARM64_D0:
19531963
return "d0";
19541964
case UNW_ARM64_D1:

0 commit comments

Comments
 (0)