summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc/amd64
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2020-06-09 12:07:06 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2020-06-09 12:07:06 +0000
commit54d9989ce966882c8e17fa8fa8588552c1505ae6 (patch)
tree11cd0abd0778703bae0dbf6d958a70f41409212b /usr/src/lib/libc/amd64
parent322423e0a7dee54a57e00d4e7cd85ab7d7a265b7 (diff)
parentb3263c9871d056ea54cca24eaeedd5a41fd333de (diff)
downloadillumos-joyent-54d9989ce966882c8e17fa8fa8588552c1505ae6.tar.gz
[illumos-gate merge]
commit b3263c9871d056ea54cca24eaeedd5a41fd333de 12826 update to smatch 0.6.1-rc1-il-6 commit e1fb6a07e9492184a949d5a3ba446ff53b888a2b 12777 libc unwinding confused by indirect pointer encoding commit eda3ef2de2d15b389090f6ef953edaea3daaace4 12689 Want c11 uchar.h commit e214b19eaa16fec1fa60a97227778103f598336f 12577 px: NULL pointer errors
Diffstat (limited to 'usr/src/lib/libc/amd64')
-rw-r--r--usr/src/lib/libc/amd64/Makefile4
-rw-r--r--usr/src/lib/libc/amd64/unwind/call_frame_inst.c41
2 files changed, 38 insertions, 7 deletions
diff --git a/usr/src/lib/libc/amd64/Makefile b/usr/src/lib/libc/amd64/Makefile
index c21ef76ee2..a134e08c87 100644
--- a/usr/src/lib/libc/amd64/Makefile
+++ b/usr/src/lib/libc/amd64/Makefile
@@ -747,6 +747,8 @@ PORTI18N_COND= \
PORTLOCALE= \
big5.o \
btowc.o \
+ c16rtomb.o \
+ c32rtomb.o \
collate.o \
collcmp.o \
euc.o \
@@ -772,6 +774,8 @@ PORTLOCALE= \
mbftowc.o \
mblen.o \
mbrlen.o \
+ mbrtoc16.o \
+ mbrtoc32.o \
mbrtowc.o \
mbsinit.o \
mbsnrtowcs.o \
diff --git a/usr/src/lib/libc/amd64/unwind/call_frame_inst.c b/usr/src/lib/libc/amd64/unwind/call_frame_inst.c
index 82d357fb0c..3e23a5e25b 100644
--- a/usr/src/lib/libc/amd64/unwind/call_frame_inst.c
+++ b/usr/src/lib/libc/amd64/unwind/call_frame_inst.c
@@ -23,6 +23,7 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright 2020 Oxide Computer Company
*/
/*
@@ -471,19 +472,25 @@ _Unw_get_val(void **datap, ptrdiff_t reloc,
static uint64_t
get_encoded_val(void **datap, ptrdiff_t reloc, int enc)
{
- int val = enc & 0xf;
- int rel = (enc >> 4) & 0xf;
+ const uint8_t val = enc & 0xf;
+ const uint8_t rel = enc & 0x70;
+ const boolean_t indirect = (enc & 0x80) != 0;
intptr_t loc = ((intptr_t)*datap) + reloc;
uint64_t res = 0;
+ /*
+ * Calculate the offset represented by the pointer encoding. These
+ * DWARF extensions are defined in the Core Generic document set of the
+ * LSB specification.
+ */
switch (val) {
case 0x01:
res = _Unw_get_val(datap, reloc, ULEB128, 1, 1, 0);
break;
- case 0x2:
+ case 0x02:
res = _Unw_get_val(datap, reloc, UNUM16, 1, 1, 0);
break;
- case 0x3:
+ case 0x03:
res = _Unw_get_val(datap, reloc, UNUM32, 1, 1, 0);
break;
case 0x04:
@@ -502,11 +509,11 @@ get_encoded_val(void **datap, ptrdiff_t reloc, int enc)
res = _Unw_get_val(datap, reloc, SNUM64, 1, 1, 0);
break;
}
-
switch (rel) {
- case 0:
+ case 0x00:
break;
- case 1:
+ case 0x10:
+ /* DW_EH_PE_pcrel */
if (res != 0)
res += loc;
break;
@@ -514,6 +521,26 @@ get_encoded_val(void **datap, ptrdiff_t reloc, int enc)
/* remainder not implemented */
break;
}
+
+ /*
+ * The high bit of the pointer encoding (DW_EH_PE_indirect = 0x80)
+ * indicates that a pointer-sized value should be read from the
+ * calculated address as the final result.
+ *
+ * Shockingly, this is not documented in any specification to date, but
+ * has been implemented in various unwind implementations through
+ * reverse-engineering of GCC.
+ */
+ if (indirect) {
+ void *addr = (void *)(uintptr_t)res;
+
+ /*
+ * Built only for amd64, we can count on a 64-bit pointer size
+ * for the indirect handling.
+ */
+ res = _Unw_get_val(&addr, reloc, UNUM64, 1, 1, 0);
+ }
+
return (res);
}