Mercurial > illumos > git > illumos-joyent
changeset 25258:4076af232ed9
12226 libctf needs to handle DW_AT_count based array sizing
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Jason King <jason.king@joyent.com>
Approved by: Dan McDonald <danmcd@joyent.com>
author | Robert Mustacchi <rm@fingolfin.org> |
---|---|
date | Thu, 09 Jul 2020 09:08:47 -0700 |
parents | b821679919bb |
children | 2d1e73c83a13 |
files | usr/src/lib/libctf/common/ctf_dwarf.c |
diffstat | 1 files changed, 24 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/lib/libctf/common/ctf_dwarf.c Wed Jul 29 22:37:40 2020 +0000 +++ b/usr/src/lib/libctf/common/ctf_dwarf.c Thu Jul 09 09:08:47 2020 -0700 @@ -1464,21 +1464,37 @@ Dwarf_Half form; Dwarf_Error derr; const char *formstr = NULL; + uint_t adj = 0; int ret = 0; ctf_dprintf("setting array upper bound\n"); ar->ctr_nelems = 0; - ret = ctf_dwarf_attribute(cup, range, DW_AT_upper_bound, &attr); /* - * Treat the lack of an upper bound attribute as a zero element array - * and return success, otherwise return the error. + * Different compilers use different attributes to indicate the size of + * an array. GCC has traditionally used DW_AT_upper_bound, while Clang + * uses DW_AT_count. They have slightly different semantics. DW_AT_count + * indicates the total number of elements that are present, while + * DW_AT_upper_bound indicates the last index, hence we need to add one + * to that index to get the count. + * + * We first search for DW_AT_count and then for DW_AT_upper_bound. If we + * find neither, then we treat the lack of this as a zero element array. + * Our value is initialized assuming we find a DW_AT_count value. */ - if (ret != 0) { - if (ret == ENOENT) + ret = ctf_dwarf_attribute(cup, range, DW_AT_count, &attr); + if (ret != 0 && ret != ENOENT) { + return (ret); + } else if (ret == ENOENT) { + ret = ctf_dwarf_attribute(cup, range, DW_AT_upper_bound, &attr); + if (ret != 0 && ret != ENOENT) { + return (ret); + } else if (ret == ENOENT) { return (0); - return (ret); + } else { + adj = 1; + } } if (dwarf_whatform(attr, &form, &derr) != DW_DLV_OK) { @@ -1520,14 +1536,14 @@ switch (form) { case DW_FORM_sdata: if (dwarf_formsdata(attr, &sval, &derr) == DW_DLV_OK) { - ar->ctr_nelems = sval + 1; + ar->ctr_nelems = sval + adj; goto done; } break; case DW_FORM_udata: default: if (dwarf_formudata(attr, &uval, &derr) == DW_DLV_OK) { - ar->ctr_nelems = uval + 1; + ar->ctr_nelems = uval + adj; goto done; } break;