diff options
| author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2020-06-09 12:07:06 +0000 |
|---|---|---|
| committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2020-06-09 12:07:06 +0000 |
| commit | 54d9989ce966882c8e17fa8fa8588552c1505ae6 (patch) | |
| tree | 11cd0abd0778703bae0dbf6d958a70f41409212b /usr/src/lib/libc/amd64 | |
| parent | 322423e0a7dee54a57e00d4e7cd85ab7d7a265b7 (diff) | |
| parent | b3263c9871d056ea54cca24eaeedd5a41fd333de (diff) | |
| download | illumos-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/Makefile | 4 | ||||
| -rw-r--r-- | usr/src/lib/libc/amd64/unwind/call_frame_inst.c | 41 |
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); } |
