Bug #10854
closedempty struct array confuses CTF
100%
Description
As reported by Serapheim. Using GCC7:
$ cat a.c int q[] = {}; $ /home/gk/src/gcc/proto.strap/usr/gcc/7/bin/gcc -gdwarf-2 -c -o a.o a.c $ ctfconvert a.o ctfconvert: failed to get unsigned attribute for type: DW_DLE_ATTR_FORM_BAD
At a guess, it's because of this:
<2><26>: Abbrev Number: 3 (DW_TAG_subrange_type) <27> DW_AT_type : <0x2d> <2b> DW_AT_upper_bound : -1
Related issues
Updated by John Levon over 3 years ago
To answer richlowe's question in #10922 - we probably want to explicitly special case -1 here...
Updated by Gergő Mihály Doma over 3 years ago
- Has duplicate Bug #10922: libctf apparently erroneously assumes upper-bound of array size is non-negative added
Updated by Joshua M. Clulow over 2 years ago
- Has duplicate Bug #12889: ctfconvert fails on empty array added
Updated by Jason King over 2 years ago
Doing some more testing, what seems to be happening is that gcc4 always uses an unsigned type to encode the upper bound, even if the value is -1
. gcc7 uses a signed type with a value of -1 for arrays with no known upper bound, but an unsigned type for arrays with known values.
For example:
root@pi:~# cat ctftest.c int test[] = { };
From gcc7:
<2><26>: Abbrev Number: 3 (DW_TAG_subrange_type) <27> DW_AT_type : <0x2d> <2b> DW_AT_upper_bound : -1 <2><2c>: Abbrev Number: 0 <1><2d>: Abbrev Number: 4 (DW_TAG_base_type) <2e> DW_AT_byte_size : 4 <2f> DW_AT_encoding : 5 (signed) <30> DW_AT_name : (indirect string, offset: 0x0): ssizetype ... 3 DW_TAG_subrange_type [no children] DW_AT_type DW_FORM_ref4 DW_AT_upper_bound DW_FORM_sdata DW_AT value: 0 DW_FORM value: 0 ...
From gcc 4.4.4:
root@pi:~# /opt/gcc-4.4.4/bin/gcc -g -o ctftest-gcc4.o -c ctftest.c root@pi:~# /usr/gnu/x86_64-pc-solaris2.11/bin/objdump -g ctftest-gcc4.o ... 3 DW_TAG_subrange_type [no children] DW_AT_type DW_FORM_ref4 DW_AT_upper_bound DW_FORM_data8 DW_AT value: 0 DW_FORM value: 0 ... <2><2e>: Abbrev Number: 3 (DW_TAG_subrange_type) <2f> DW_AT_type : <0x3c> <33> DW_AT_upper_bound : 0xffffffffffffffff <2><3b>: Abbrev Number: 0 <1><3c>: Abbrev Number: 4 (DW_TAG_base_type) <3d> DW_AT_byte_size : 4 <3e> DW_AT_encoding : 7 (unsigned) <3f> DW_AT_name : (indirect string, offset: 0x0): unsigned int
However, for a non-zero array:
root@pi:~# cat ctftest2.c int test[] = { 1 }; root@pi:~# /opt/gcc-7/bin/gcc -gdwarf-2 -g -c ctftest2.c root@pi:~# /usr/gnu/x86_64-pc-solaris2.11/bin/objdump -g ctftest2.o ... <2><26>: Abbrev Number: 3 (DW_TAG_subrange_type) <27> DW_AT_type : <0x2d> <2b> DW_AT_upper_bound : 0 <2><2c>: Abbrev Number: 0 <1><2d>: Abbrev Number: 4 (DW_TAG_base_type) <2e> DW_AT_byte_size : 4 <2f> DW_AT_encoding : 7 (unsigned) <30> DW_AT_name : (indirect string, offset: 0x0): unsigned int ... 3 DW_TAG_subrange_type [no children] DW_AT_type DW_FORM_ref4 DW_AT_upper_bound DW_FORM_data1 DW_AT value: 0 DW_FORM value: 0
And gcc4.4.4:
root@pi:~# /opt/gcc-4.4.4/bin/gcc -gdwarf-2 -g -o ctftest2-gcc4.o -c ctftest2.c root@pi:~# /usr/gnu/x86_64-pc-solaris2.11/bin/objdump -g ctftest2-gcc4.o ... 3 DW_TAG_subrange_type [no children] DW_AT_type DW_FORM_ref4 DW_AT_upper_bound DW_FORM_data1 DW_AT value: 0 DW_FORM value: 0 ... <2><2e>: Abbrev Number: 3 (DW_TAG_subrange_type) <2f> DW_AT_type : <0x35> <33> DW_AT_upper_bound : 0 <2><34>: Abbrev Number: 0 <1><35>: Abbrev Number: 4 (DW_TAG_base_type) <36> DW_AT_byte_size : 4 <37> DW_AT_encoding : 7 (unsigned) <38> DW_AT_name : (indirect string, offset: 0x0): unsigned int
Note: I also tried without -gdwarf-2
and the resulting dwarf info for this case was identical. I also double checked VLAs as well, and they also act like arrays with known dimensions (e.g. upper bound is an unsigned type, though obviously the expression for the value is different).
Updated by Jason King over 2 years ago
For testing, I built illumos-gate with the ctf changes.
Additionally, I ran the updated ctf tests in the util-test package. These were run with gcc-4.4.4, gcc 7.5.0, gcc 8.4.0, gcc 9.3.0, gcc 10.1.0 (the versions available on omniosce bloody).
For all of the compilers except gcc-4.4.4, the ctftest-merge-no-ctf and ctftest-convert-no-dwarf fail:
Running /opt/util-tests/tests/ctf/ctftest-merge-no-ctf in /tmp/ctftest.134191 ctftest-merge-no-ctf: ctfmerge should fail if one C-source lacks CTF ctftest-merge-no-ctf: ctfmerge should allow a .cc file to lack CTF ctftest-merge-no-ctf: ctfmerge should allow an .s file to lack CTF ld: fatal: file file1.o: wrong ELF class: ELFCLASS64 ld: fatal: file processing errors. No output written to files.o TEST FAILED: /opt/util-tests/tests/ctf/ctftest-merge-no-ctf failed Running /opt/util-tests/tests/ctf/ctftest-convert-no-dwarf in /tmp/ctftest.134191 ctftest-convert-no-dwarf: An empty file should fail conversion due to no DWARF ctftest-convert-no-dwarf: A file missing DWARF should fail conversion ctftest-convert-no-dwarf: A binary with DWARF but 0 debug dies should fail conversion ctftest-convert-no-dwarf: One C file missing DWARF should fail ctfconvert ctftest-convert-no-dwarf: One .cc file missing DWARF should pass ctftest-convert-no-dwarf: One .s file missing DWARF should pass ld: fatal: file file4.o: wrong ELF class: ELFCLASS32 ld: fatal: file processing errors. No output written to mybin collect2: error: ld returned 1 exit status TEST FAILED: /opt/util-tests/tests/ctf/ctftest-convert-no-dwarf failed
The issue appears to due to the assembler and C compilers defaulting to different bitness for the non 4.4.4 gccs.
There are also warnings w/ gcc10:
ld: warning: symbol 'dup2' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-2.32.c.o type=OBJT; file /lib/libc.so type=FUNC); /tmp/ctftest.134191-test-merge-dedup/test-merge-2.32.c.o definition taken ld: warning: symbol 'dup2' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-2.32.c.o type=OBJT; file /lib/libc.so type=FUNC); ld: warning: symbol 'dup3' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-3.32.c.o type=OBJT; file /lib/libc.so type=FUNC); /tmp/ctftest.134191-test-merge-dedup/test-merge-3.32.c.o definition taken ld: warning: symbol 'dup3' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-3.32.c.o type=OBJT; file /lib/libc.so type=FUNC); ld: warning: symbol 'dup2' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-2.64.c.o type=OBJT; file /lib/amd64/libc.so type=FUNC); /tmp/ctftest.134191-test-merge-dedup/test-merge-2.64.c.o definition taken ld: warning: symbol 'dup2' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-2.64.c.o type=OBJT; file /lib/amd64/libc.so type=FUNC); ld: warning: symbol 'dup3' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-3.64.c.o type=OBJT; file /lib/amd64/libc.so type=FUNC); /tmp/ctftest.134191-test-merge-dedup/test-merge-3.64.c.o definition taken ld: warning: symbol 'dup3' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-3.64.c.o type=OBJT; file /lib/amd64/libc.so type=FUNC); ld: warning: symbol 'dup2' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-2.32.m.o type=OBJT; file /lib/libc.so type=FUNC); /tmp/ctftest.134191-test-merge-dedup/test-merge-2.32.m.o definition taken ld: warning: symbol 'dup2' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-2.32.m.o type=OBJT; file /lib/libc.so type=FUNC); ld: warning: symbol 'dup3' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-3.32.m.o type=OBJT; file /lib/libc.so type=FUNC); /tmp/ctftest.134191-test-merge-dedup/test-merge-3.32.m.o definition taken ld: warning: symbol 'dup3' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-3.32.m.o type=OBJT; file /lib/libc.so type=FUNC); ld: warning: symbol 'dup2' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-2.64.m.o type=OBJT; file /lib/amd64/libc.so type=FUNC); /tmp/ctftest.134191-test-merge-dedup/test-merge-2.64.m.o definition taken ld: warning: symbol 'dup2' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-2.64.m.o type=OBJT; file /lib/amd64/libc.so type=FUNC); ld: warning: symbol 'dup3' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-3.64.m.o type=OBJT; file /lib/amd64/libc.so type=FUNC); /tmp/ctftest.134191-test-merge-dedup/test-merge-3.64.m.o definition taken ld: warning: symbol 'dup3' has differing types: (file /tmp/ctftest.134191-test-merge-dedup/test-merge-3.64.m.o type=OBJT; file /lib/amd64/libc.so type=FUNC);
However again, these appear to not be related -- and appear to be due to conflicts with function names in libc (I didn't look too closely -- but I'm guessing maybe some default visibility differences with gcc 10).
gcc 4.4.4 had the following failures:
check-enum: enum char_enum has bad size, expected 1, found 4 check-enum: enum short_enum has bad size, expected 2, found 4 check-enum: enum ll_enum has bad size, expected 8, found 4 TEST FAILED: check for /opt/util-tests/tests/ctf/test-enum.c, /opt/util-tests/tests/ctf/check-enum, failed check-enum: enum char_enum has bad size, expected 1, found 4 check-enum: enum short_enum has bad size, expected 2, found 4 check-enum: enum ll_enum has bad size, expected 8, found 4 TEST FAILED: check for /opt/util-tests/tests/ctf/test-enum.c, /opt/util-tests/tests/ctf/check-enum, failed ... Undefined first referenced symbol in file arc4random /tmp/ctftest.136365-test-merge-reduction/test-global.32.c.o (symbol belongs to implicit dependency /lib/libc.so.1) ld: fatal: symbol referencing errors. No output written to /tmp/ctftest.136365-test-merge-reduction/test-merge-reduction-32c.so.1 collect2: ld returned 1 exit status make: Fatal error: Command failed for target `/tmp/ctftest.136365-test-merge-reduction/test-merge-reduction-32c.so.1' TEST FAILED: failed to build /opt/util-tests/tests/ctf/test-merge-reduction
The first just appears to be due to differences in how it stores enums (sizeof (int) vs. smallest int). The second also doesn't appear to be related.
I tried clang, but the tests failed in general, and seem to be at least in part due to #12226.
Updated by Jason King over 2 years ago
I also ran the new ctf tests against the current (unmodified) ctfconvert, and the ctf_array test fails with ctfconvert: failed to get unsigned attribute for type: DW_DLE_ATTR_FORM_BAD
as expected.
Updated by Robert Mustacchi over 2 years ago
Updated by Dan McDonald over 2 years ago
- Related to Bug #12898: ctf enum size detection should use DW_AT_byte_size added
Updated by Electric Monk over 2 years ago
- Status changed from New to Closed
- % Done changed from 0 to 100
git commit 5f9772673df89384a3fa8f1cbfcccd8d331f83ff
commit 5f9772673df89384a3fa8f1cbfcccd8d331f83ff Author: Jason King <jason.king@joyent.com> Date: 2020-06-30T01:00:59.000Z 10854 empty struct array confuses CTF Reviewed by: Andy Fiddaman <omnios@citrus-it.co.uk> Reviewed by: Robert Mustacchi <rm@fingolfin.org> Approved by: Dan McDonald <danmcd@joyent.com>
Updated by Jason King over 2 years ago
Adding to the ticket some additional testing details from the RTI:
Comparing a proto area and a proto area without the change:
plain=path_to_proto_of_build_wo_change cd proto/root_i386 find bin usr/bin sbin usr/sbin lib usr/lib -type f | while read path; do ctfdiff -q $path $plain/$path >/dev/null 2>&1 [[ $? -eq 1 ]] && echo "$path differs” done
(I looked for a return value of 1 specifically to ignore files w/o ctf data and only focus on those ctfdiff reported as having differences).
Unfortunately, that seems to have flagged every object with CTF data. It seems multiple objects or functions with the same name (e.g. two .c files in the same resulting object defining ’static foo_t object’ or ’static void func(…)’) confuses ctfdiff:
Picking an object that was flagged for differences:
root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# ctfdiff usr/lib/security/amd64/pkcs11_softtoken.so.1 $plain/usr/lib/security/amd64/pkcs11_softtoken.so.1 … 289 lines of output omitted… ctf container /ws/illumos-gate/proto-plain/root_i386/usr/lib/security/amd64/pkcs11_softtoken.so.1 object ecCurve_map (1397) is different root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# ctfdump -c usr/lib/security/amd64/pkcs11_softtoken.so.1 > /tmp/1 root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# ctfdump -c $plain/usr/lib/security/amd64/pkcs11_softtoken.so.1 > /tmp/2 root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# diff -u /tmp/1 /tmp/2 No differences encountered root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# grep ecCurve_map /tmp/1 extern const ECCurveParams *ecCurve_map[59]; extern const ECCurveParams *ecCurve_map[59]; extern const ECCurveParams *ecCurve_map[59]; extern const ECCurveParams *ecCurve_map[59]; extern const ECCurveParams *ecCurve_map[59]; extern const ECCurveParams *ecCurve_map[59]; root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# grep ecCurve_map /tmp/2 extern const ECCurveParams *ecCurve_map[59]; extern const ECCurveParams *ecCurve_map[59]; extern const ECCurveParams *ecCurve_map[59]; extern const ECCurveParams *ecCurve_map[59]; extern const ECCurveParams *ecCurve_map[59]; extern const ECCurveParams *ecCurve_map[59];
Picking another ‘mismatch’ at random:
root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# ctfdiff usr/bin/svcs $plain/usr/bin/svcs ctf container /ws/illumos-gate/proto-plain/root_i386/usr/bin/svcs object g_pg (213) is different ctf container /ws/illumos-gate/proto-plain/root_i386/usr/bin/svcs object g_prop (214) is different ctf container /ws/illumos-gate/proto-plain/root_i386/usr/bin/svcs object g_val (215) is different root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# ctfdump -c usr/bin/svcs > /tmp/1 root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# ctfdump -c $plain/usr/bin/svcs > /tmp/2 root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# diff -u /tmp/1 /tmp/2 No differences encountered root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# grep -E 'g_pg|g_prop|g_val' /tmp/1 /tmp/2 /tmp/1:extern scf_propertygroup_t * g_pg; /tmp/1:extern scf_propertygroup_t * g_pg; /tmp/1:extern scf_property_t * g_prop; /tmp/1:extern scf_property_t * g_prop; /tmp/1:extern scf_value_t * g_val; /tmp/1:extern scf_value_t * g_val; /tmp/1:extern char * g_value; /tmp/1:extern size_t g_value_sz; /tmp/1:extern void get_restarter_string_prop(scf_instance_t *, const char *, char *, size_t); /tmp/2:extern scf_propertygroup_t * g_pg; /tmp/2:extern scf_propertygroup_t * g_pg; /tmp/2:extern scf_property_t * g_prop; /tmp/2:extern scf_property_t * g_prop; /tmp/2:extern scf_value_t * g_val; /tmp/2:extern scf_value_t * g_val; /tmp/2:extern char * g_value; /tmp/2:extern size_t g_value_sz; /tmp/2:extern void get_restarter_string_prop(scf_instance_t *, const char *, char *, size_t);
I’ve done a few more spot checks with similar results… just comparing the `ctfdump -c` output for the same paths (e.g.
find bin usr/bin sbin usr/sbin lib usr/lib -type f | while read path; do diff -u <(ctfdump -c $path 2>/dev/null) <(ctfdump -c $plain/$path 2>/dev/null) [[ $? -eq 1 ]] && echo "$path has differences” done
only flags libctf.so.1 (32 and 64 bit versions) which is expected (new function added by the change) so I’m not sure what the ‘right' way to do the comparison is..
For kernel objects,
find kernel usr/kernel -type f | while read path; do ctfdiff -p kernel/amd64/genunix -P $plain/kernel/amd64/genunix $path $plain/$path >/dev/null 2>&1 [[ $? -eq 1 ]] && echo "$path has differences” done
Seemed to flag every kernel module, but picking a random module:
root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# ctfdiff -p kernel/amd64/genunix -P $plain/kernel/amd64/genunix kernel/drv/amd64/zfs $plain/kernel/drv/amd64/zfs ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs function valid_char (2270) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs function valid_char (2293) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs function dataset_name_hidden (2539) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.39705 (633) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.31131 (778) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.31781 (868) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.32192 (889) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.40665 (912) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.31565 (974) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.31745 (982) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.30958 (1045) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.27742 (1527) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.31780 (1565) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.30237 (1928) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.30446 (1942) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.30102 (1964) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.39756 (2807) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.39890 (2817) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.40024 (2827) is different ctf container /ws/illumos-gate/proto-plain/root_i386/kernel/drv/amd64/zfs object __func__.41599 (2870) is different
(I’m almost definite the ‘__func__’ entries can be ignored, so I will)…
root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# ctfdump -cp kernel/amd64/genunix kernel/drv/amd64/zfs > /tmp/1 root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# ctfdump -cp $plain/kernel/amd64/genunix $plain/kernel/drv/amd64/zfs > /tmp/2 root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# diff -u /tmp/1 /tmp/2 No differences encountered root@pi:/ws/illumos-gate/proto/root_i386 (ctf_array)# grep -E 'valid_char|dataset_name_hidden' /tmp/1 /tmp/2 /tmp/1:extern boolean_t dataset_name_hidden(const char *); /tmp/1:extern boolean_t dataset_name_hidden(const char *); /tmp/1:extern int valid_char(char, boolean_t); /tmp/1:extern int valid_char(char); /tmp/1:extern int valid_char(char); /tmp/2:extern boolean_t dataset_name_hidden(const char *); /tmp/2:extern boolean_t dataset_name_hidden(const char *); /tmp/2:extern int valid_char(char, boolean_t); /tmp/2:extern int valid_char(char); /tmp/2:extern int valid_char(char);
So this seems to be a similar issue as with the user land objects.. running a similar test using ctfdump -c
find kernel usr/kernel -type f | while read path; do diff -u <(ctfdump -c -p kernel/amd64/genunix $path 2>/dev/null) <(ctfdump -c -p $plain/kernel/amd64/genunix $plain/$path 2>/dev/null) > dev/null [[ $? -eq 1 ]] && echo "$path has differences” done
Showed no differences
Additionally, I used the ctfwsdiff script from #12222
Using ctfdump: /usr/bin/ctfdump Gathering files from /ws/illumos-gate/proto.orig... Testing files... diff found: /ws/illumos-gate/proto.orig/root_i386/lib/libctf.so.1 diff found: /ws/illumos-gate/proto.orig/root_i386/lib/amd64/libctf.so.1 Missing /ws/illumos-gate/proto/root_i386/usr/perl5/5.30/lib/Sun/Solaris/Pg.pm from proto area The perl module is just related to some OmniOS perl updates that came in over the weekend. For the libctf differences: root@pi:/ws/illumos-gate (ctf_array)# diff -u <(ctfdump -c proto.orig/root_i386/lib/libctf.so.1) <(ctfdump -c proto/root_i386/lib/libctf.so.1) --- /dev/fd/63 Mon Jun 29 11:53:28 2020 +++ /dev/fd/62 Mon Jun 29 11:53:28 2020 @@ -1216,6 +1216,7 @@ extern void ctf_dtd_insert(ctf_file_t *, ctf_dtdef_t *); extern ctf_dtdef_t * ctf_dtd_lookup(ctf_file_t *, ctf_id_t); extern ctf_file_t * ctf_dup(ctf_file_t *); +extern int ctf_dwarf_array_upper_bound(ctf_cu_t *, Dwarf_Die, ctf_arinfo_t *); extern int ctf_dwarf_attribute(ctf_cu_t *, Dwarf_Die, Dwarf_Half, Dwarf_Attribute *); extern int ctf_dwarf_boolean(ctf_cu_t *, Dwarf_Die, Dwarf_Half, Dwarf_Bool *); extern int ctf_dwarf_check_missing(ctf_cu_t *, size_t, Elf *, char *, size_t); root@pi:/ws/illumos-gate (ctf_array)# diff -u <(ctfdump -c proto.orig/root_i386/lib/amd64/libctf.so.1) <(ctfdump -c proto/root_i386/lib/amd64/libctf.so.1) --- /dev/fd/63 Mon Jun 29 11:53:46 2020 +++ /dev/fd/62 Mon Jun 29 11:53:46 2020 @@ -1200,6 +1200,7 @@ extern void ctf_dtd_insert(ctf_file_t *, ctf_dtdef_t *); extern ctf_dtdef_t * ctf_dtd_lookup(ctf_file_t *, ctf_id_t); extern ctf_file_t * ctf_dup(ctf_file_t *); +extern int ctf_dwarf_array_upper_bound(ctf_cu_t *, Dwarf_Die, ctf_arinfo_t *); extern int ctf_dwarf_attribute(ctf_cu_t *, Dwarf_Die, Dwarf_Half, Dwarf_Attribute *); extern int ctf_dwarf_boolean(ctf_cu_t *, Dwarf_Die, Dwarf_Half, Dwarf_Bool *); extern int ctf_dwarf_check_missing(ctf_cu_t *, size_t, Elf *, char *, size_t); Which is expected with the change.