GNU Binutils with patches for OS216
修訂 | dde074f887ff9f45dec8155aefcba7054c98f5b6 (tree) |
---|---|
時間 | 2019-09-24 22:06:32 |
作者 | Nick Alcock <nick.alcock@orac...> |
Commiter | Nick Alcock |
libctf: properly handle ctf_add_type of forwards and self-reffing structs
The code to handle structures (and unions) that refer to themselves in
ctf_add_type is extremely dodgy. It works by looking through the list
of not-yet-committed types for a structure with the same name as the
structure in question and assuming, if it finds it, that this must be a
reference to the same type. This is a linear search that gets ever
slower as the dictionary grows, requiring you to call ctf_update at
intervals to keep performance tolerable: but if you do that, you run
into the problem that if a forward declared before the ctf_update is
changed to a structure afterwards, ctf_update explodes.
The last commit fixed most of this: this commit can use it, adding a new
ctf_add_processing hash that tracks source type IDs that are currently
being processed and uses it to avoid infinite recursion rather than the
dynamic type list: we split ctf_add_type into a ctf_add_type_internal,
so that ctf_add_type itself can become a wrapper that empties out this
being-processed hash once the entire recursive type addition is over.
Structure additions themselves avoid adding their dependent types
quite so much by checking the type mapping and avoiding re-adding types
we already know we have added.
We also add support for adding forwards to dictionaries that already
contain the thing they are a forward to: we just silently return the
original type.
v4: return existing struct/union/enum types properly, rather than using
libctf/
* ctf-impl.h (ctf_file_t) <ctf_add_processing>: New.
* ctf-open.c (ctf_file_close): Free it.
* ctf-create.c (ctf_serialize): Adjust.
(membcmp): When reporting a conflict due to an error, report the
error.
(ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to...
(ctf_add_type_internal): ... this. Hand back types we are already
in the middle of adding immediately. Hand back structs/unions with
the same number of members immediately. Do not walk the dynamic
list. Call ctf_add_type_internal, not ctf_add_type. Handle
forwards promoted to other types and the inverse case identically.
Add structs to the mapping as soon as we intern them, before they
gain any members.
@@ -1,3 +1,19 @@ | ||
1 | +2019-08-07 Nick Alcock <nick.alcock@oracle.com> | |
2 | + | |
3 | + * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. | |
4 | + * ctf-open.c (ctf_file_close): Free it. | |
5 | + * ctf-create.c (ctf_serialize): Adjust. | |
6 | + (membcmp): When reporting a conflict due to an error, report the | |
7 | + error. | |
8 | + (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... | |
9 | + (ctf_add_type_internal): ... this. Hand back types we are already | |
10 | + in the middle of adding immediately. Hand back structs/unions with | |
11 | + the same number of members immediately. Do not walk the dynamic | |
12 | + list. Call ctf_add_type_internal, not ctf_add_type. Handle | |
13 | + forwards promoted to other types and the inverse case identically. | |
14 | + Add structs to the mapping as soon as we intern them, before they | |
15 | + gain any members. | |
16 | + | |
1 | 17 | 2019-08-09 Nick Alcock <nick.alcock@oracle.com> |
2 | 18 | |
3 | 19 | * ctf-impl.h (ctf_names_t): New. |
@@ -525,6 +525,7 @@ ctf_serialize (ctf_file_t *fp) | ||
525 | 525 | nfp->ctf_dvhash = fp->ctf_dvhash; |
526 | 526 | nfp->ctf_dvdefs = fp->ctf_dvdefs; |
527 | 527 | nfp->ctf_dtoldid = fp->ctf_dtoldid; |
528 | + nfp->ctf_add_processing = fp->ctf_add_processing; | |
528 | 529 | nfp->ctf_snapshots = fp->ctf_snapshots + 1; |
529 | 530 | nfp->ctf_specific = fp->ctf_specific; |
530 | 531 | nfp->ctf_ptrtab = fp->ctf_ptrtab; |
@@ -553,6 +554,7 @@ ctf_serialize (ctf_file_t *fp) | ||
553 | 554 | fp->ctf_str_atoms = NULL; |
554 | 555 | fp->ctf_prov_strtab = NULL; |
555 | 556 | memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t)); |
557 | + fp->ctf_add_processing = NULL; | |
556 | 558 | fp->ctf_ptrtab = NULL; |
557 | 559 | fp->ctf_link_inputs = NULL; |
558 | 560 | fp->ctf_link_outputs = NULL; |
@@ -1527,7 +1529,8 @@ enumcmp (const char *name, int value, void *arg) | ||
1527 | 1529 | |
1528 | 1530 | if (ctf_enum_value (ctb->ctb_file, ctb->ctb_type, name, &bvalue) < 0) |
1529 | 1531 | { |
1530 | - ctf_dprintf ("Conflict due to member %s iteration error.\n", name); | |
1532 | + ctf_dprintf ("Conflict due to member %s iteration error: %s.\n", name, | |
1533 | + ctf_errmsg (ctf_errno (ctb->ctb_file))); | |
1531 | 1534 | return 1; |
1532 | 1535 | } |
1533 | 1536 | if (value != bvalue) |
@@ -1557,7 +1560,8 @@ membcmp (const char *name, ctf_id_t type _libctf_unused_, unsigned long offset, | ||
1557 | 1560 | |
1558 | 1561 | if (ctf_member_info (ctb->ctb_file, ctb->ctb_type, name, &ctm) < 0) |
1559 | 1562 | { |
1560 | - ctf_dprintf ("Conflict due to member %s iteration error.\n", name); | |
1563 | + ctf_dprintf ("Conflict due to member %s iteration error: %s.\n", name, | |
1564 | + ctf_errmsg (ctf_errno (ctb->ctb_file))); | |
1561 | 1565 | return 1; |
1562 | 1566 | } |
1563 | 1567 | if (ctm.ctm_offset != offset) |
@@ -1603,11 +1607,13 @@ membadd (const char *name, ctf_id_t type, unsigned long offset, void *arg) | ||
1603 | 1607 | following the source type's links and embedded member types. If the |
1604 | 1608 | destination container already contains a named type which has the same |
1605 | 1609 | attributes, then we succeed and return this type but no changes occur. */ |
1606 | -ctf_id_t | |
1607 | -ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | |
1610 | +static ctf_id_t | |
1611 | +ctf_add_type_internal (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type, | |
1612 | + ctf_file_t *proc_tracking_fp) | |
1608 | 1613 | { |
1609 | 1614 | ctf_id_t dst_type = CTF_ERR; |
1610 | 1615 | uint32_t dst_kind = CTF_K_UNKNOWN; |
1616 | + ctf_file_t *tmp_fp = dst_fp; | |
1611 | 1617 | ctf_id_t tmp; |
1612 | 1618 | |
1613 | 1619 | const char *name; |
@@ -1618,7 +1624,6 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1618 | 1624 | ctf_encoding_t src_en, dst_en; |
1619 | 1625 | ctf_arinfo_t src_ar, dst_ar; |
1620 | 1626 | |
1621 | - ctf_dtdef_t *dtd; | |
1622 | 1627 | ctf_funcinfo_t ctc; |
1623 | 1628 | |
1624 | 1629 | ctf_id_t orig_src_type = src_type; |
@@ -1638,6 +1643,33 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1638 | 1643 | flag = LCTF_INFO_ISROOT (src_fp, src_tp->ctt_info); |
1639 | 1644 | vlen = LCTF_INFO_VLEN (src_fp, src_tp->ctt_info); |
1640 | 1645 | |
1646 | + /* If this is a type we are currently in the middle of adding, hand it | |
1647 | + straight back. (This lets us handle self-referential structures without | |
1648 | + considering forwards and empty structures the same as their completed | |
1649 | + forms.) */ | |
1650 | + | |
1651 | + tmp = ctf_type_mapping (src_fp, src_type, &tmp_fp); | |
1652 | + | |
1653 | + if (tmp != 0) | |
1654 | + { | |
1655 | + if (ctf_dynhash_lookup (proc_tracking_fp->ctf_add_processing, | |
1656 | + (void *) (uintptr_t) src_type)) | |
1657 | + return tmp; | |
1658 | + | |
1659 | + /* If this type has already been added from this container, and is the same | |
1660 | + kind and (if a struct or union) has the same number of members, hand it | |
1661 | + straight back. */ | |
1662 | + | |
1663 | + if ((ctf_type_kind_unsliced (tmp_fp, tmp) == (int) kind) | |
1664 | + && (kind == CTF_K_STRUCT || kind == CTF_K_UNION | |
1665 | + || kind == CTF_K_ENUM)) | |
1666 | + { | |
1667 | + if ((dst_tp = ctf_lookup_by_id (&tmp_fp, dst_type)) != NULL) | |
1668 | + if (vlen == LCTF_INFO_VLEN (tmp_fp, dst_tp->ctt_info)) | |
1669 | + return tmp; | |
1670 | + } | |
1671 | + } | |
1672 | + | |
1641 | 1673 | forward_kind = kind; |
1642 | 1674 | if (kind == CTF_K_FORWARD) |
1643 | 1675 | forward_kind = src_tp->ctt_type; |
@@ -1697,6 +1729,9 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1697 | 1729 | if ((dst_tp = ctf_lookup_by_id (&fp, dst_type)) == NULL) |
1698 | 1730 | return CTF_ERR; |
1699 | 1731 | |
1732 | + if (ctf_type_encoding (dst_fp, dst_type, &dst_en) != 0) | |
1733 | + return CTF_ERR; /* errno set for us. */ | |
1734 | + | |
1700 | 1735 | if (LCTF_INFO_ISROOT (fp, dst_tp->ctt_info) & CTF_ADD_ROOT) |
1701 | 1736 | { |
1702 | 1737 | /* The type that we found in the hash is also root-visible. If |
@@ -1705,9 +1740,6 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1705 | 1740 | even if there is no conflict: we must check the contained type |
1706 | 1741 | too. */ |
1707 | 1742 | |
1708 | - if (ctf_type_encoding (dst_fp, dst_type, &dst_en) != 0) | |
1709 | - return CTF_ERR; /* errno set for us. */ | |
1710 | - | |
1711 | 1743 | if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0) |
1712 | 1744 | { |
1713 | 1745 | if (kind != CTF_K_SLICE) |
@@ -1723,71 +1755,17 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1723 | 1755 | } |
1724 | 1756 | else |
1725 | 1757 | { |
1726 | - /* We found a non-root-visible type in the hash. We reset | |
1727 | - dst_type to ensure that we continue to look for a possible | |
1728 | - conflict in the pending list. */ | |
1729 | - | |
1730 | - dst_type = CTF_ERR; | |
1731 | - } | |
1732 | - } | |
1733 | - } | |
1734 | - | |
1735 | - /* If the non-empty name was not found in the appropriate hash, search | |
1736 | - the list of pending dynamic definitions that are not yet committed. | |
1737 | - If a matching name and kind are found, assume this is the type that | |
1738 | - we are looking for. This is necessary to permit ctf_add_type() to | |
1739 | - operate recursively on entities such as a struct that contains a | |
1740 | - pointer member that refers to the same struct type. */ | |
1741 | - | |
1742 | - if (dst_type == CTF_ERR && name[0] != '\0') | |
1743 | - { | |
1744 | - for (dtd = ctf_list_prev (&dst_fp->ctf_dtdefs); dtd != NULL | |
1745 | - && LCTF_TYPE_TO_INDEX (src_fp, dtd->dtd_type) > dst_fp->ctf_dtoldid; | |
1746 | - dtd = ctf_list_prev (dtd)) | |
1747 | - { | |
1748 | - const char *ctt_name; | |
1749 | - | |
1750 | - if (LCTF_INFO_KIND (src_fp, dtd->dtd_data.ctt_info) == kind | |
1751 | - && dtd->dtd_data.ctt_name | |
1752 | - && ((ctt_name = ctf_strraw (src_fp, dtd->dtd_data.ctt_name)) != NULL) | |
1753 | - && strcmp (ctt_name, name) == 0) | |
1754 | - { | |
1755 | - int sroot; /* Is the src root-visible? */ | |
1756 | - int droot; /* Is the dst root-visible? */ | |
1757 | - int match; /* Do the encodings match? */ | |
1758 | - | |
1759 | - if (kind != CTF_K_INTEGER && kind != CTF_K_FLOAT && kind != CTF_K_SLICE) | |
1760 | - { | |
1761 | - ctf_add_type_mapping (src_fp, src_type, dst_fp, dtd->dtd_type); | |
1762 | - return dtd->dtd_type; | |
1763 | - } | |
1764 | - | |
1765 | - sroot = (flag & CTF_ADD_ROOT); | |
1766 | - droot = (LCTF_INFO_ISROOT (dst_fp, | |
1767 | - dtd->dtd_data. | |
1768 | - ctt_info) & CTF_ADD_ROOT); | |
1758 | + /* We found a non-root-visible type in the hash. If its encoding | |
1759 | + is the same, we can reuse it, unless it is a slice. */ | |
1769 | 1760 | |
1770 | - match = (memcmp (&src_en, &dtd->dtd_u.dtu_enc, | |
1771 | - sizeof (ctf_encoding_t)) == 0); | |
1772 | - | |
1773 | - /* If the types share the same encoding then return the id of the | |
1774 | - first unless one type is root-visible and the other is not; in | |
1775 | - that case the new type must get a new id if a match is never | |
1776 | - found. Note: slices are not certain to match even if there is | |
1777 | - no conflict: we must check the contained type too. */ | |
1778 | - | |
1779 | - if (match && sroot == droot) | |
1761 | + if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0) | |
1780 | 1762 | { |
1781 | 1763 | if (kind != CTF_K_SLICE) |
1782 | 1764 | { |
1783 | - ctf_add_type_mapping (src_fp, src_type, dst_fp, dtd->dtd_type); | |
1784 | - return dtd->dtd_type; | |
1765 | + ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type); | |
1766 | + return dst_type; | |
1785 | 1767 | } |
1786 | 1768 | } |
1787 | - else if (!match && sroot && droot) | |
1788 | - { | |
1789 | - return (ctf_set_errno (dst_fp, ECTF_CONFLICT)); | |
1790 | - } | |
1791 | 1769 | } |
1792 | 1770 | } |
1793 | 1771 | } |
@@ -1800,10 +1778,18 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1800 | 1778 | dst.ctb_type = dst_type; |
1801 | 1779 | dst.ctb_dtd = NULL; |
1802 | 1780 | |
1803 | - /* Now perform kind-specific processing. If dst_type is CTF_ERR, then | |
1804 | - we add a new type with the same properties as src_type to dst_fp. | |
1805 | - If dst_type is not CTF_ERR, then we verify that dst_type has the | |
1806 | - same attributes as src_type. We recurse for embedded references. */ | |
1781 | + /* Now perform kind-specific processing. If dst_type is CTF_ERR, then we add | |
1782 | + a new type with the same properties as src_type to dst_fp. If dst_type is | |
1783 | + not CTF_ERR, then we verify that dst_type has the same attributes as | |
1784 | + src_type. We recurse for embedded references. Before we start, we note | |
1785 | + that we are processing this type, to prevent infinite recursion: we do not | |
1786 | + re-process any type that appears in this list. The list is emptied | |
1787 | + wholesale at the end of processing everything in this recursive stack. */ | |
1788 | + | |
1789 | + if (ctf_dynhash_insert (proc_tracking_fp->ctf_add_processing, | |
1790 | + (void *) (uintptr_t) src_type, (void *) 1) < 0) | |
1791 | + return ctf_set_errno (dst_fp, ENOMEM); | |
1792 | + | |
1807 | 1793 | switch (kind) |
1808 | 1794 | { |
1809 | 1795 | case CTF_K_INTEGER: |
@@ -1822,7 +1808,8 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1822 | 1808 | /* We have checked for conflicting encodings: now try to add the |
1823 | 1809 | contained type. */ |
1824 | 1810 | src_type = ctf_type_reference (src_fp, src_type); |
1825 | - dst_type = ctf_add_type (dst_fp, src_fp, src_type); | |
1811 | + src_type = ctf_add_type_internal (dst_fp, src_fp, src_type, | |
1812 | + proc_tracking_fp); | |
1826 | 1813 | |
1827 | 1814 | if (src_type == CTF_ERR) |
1828 | 1815 | return CTF_ERR; /* errno is set for us. */ |
@@ -1835,7 +1822,8 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1835 | 1822 | case CTF_K_CONST: |
1836 | 1823 | case CTF_K_RESTRICT: |
1837 | 1824 | src_type = ctf_type_reference (src_fp, src_type); |
1838 | - src_type = ctf_add_type (dst_fp, src_fp, src_type); | |
1825 | + src_type = ctf_add_type_internal (dst_fp, src_fp, src_type, | |
1826 | + proc_tracking_fp); | |
1839 | 1827 | |
1840 | 1828 | if (src_type == CTF_ERR) |
1841 | 1829 | return CTF_ERR; /* errno is set for us. */ |
@@ -1848,8 +1836,11 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1848 | 1836 | return (ctf_set_errno (dst_fp, ctf_errno (src_fp))); |
1849 | 1837 | |
1850 | 1838 | src_ar.ctr_contents = |
1851 | - ctf_add_type (dst_fp, src_fp, src_ar.ctr_contents); | |
1852 | - src_ar.ctr_index = ctf_add_type (dst_fp, src_fp, src_ar.ctr_index); | |
1839 | + ctf_add_type_internal (dst_fp, src_fp, src_ar.ctr_contents, | |
1840 | + proc_tracking_fp); | |
1841 | + src_ar.ctr_index = ctf_add_type_internal (dst_fp, src_fp, | |
1842 | + src_ar.ctr_index, | |
1843 | + proc_tracking_fp); | |
1853 | 1844 | src_ar.ctr_nelems = src_ar.ctr_nelems; |
1854 | 1845 | |
1855 | 1846 | if (src_ar.ctr_contents == CTF_ERR || src_ar.ctr_index == CTF_ERR) |
@@ -1876,7 +1867,9 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1876 | 1867 | break; |
1877 | 1868 | |
1878 | 1869 | case CTF_K_FUNCTION: |
1879 | - ctc.ctc_return = ctf_add_type (dst_fp, src_fp, src_tp->ctt_type); | |
1870 | + ctc.ctc_return = ctf_add_type_internal (dst_fp, src_fp, | |
1871 | + src_tp->ctt_type, | |
1872 | + proc_tracking_fp); | |
1880 | 1873 | ctc.ctc_argc = 0; |
1881 | 1874 | ctc.ctc_flags = 0; |
1882 | 1875 |
@@ -1893,6 +1886,7 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1893 | 1886 | int errs = 0; |
1894 | 1887 | size_t size; |
1895 | 1888 | ssize_t ssize; |
1889 | + ctf_dtdef_t *dtd; | |
1896 | 1890 | |
1897 | 1891 | /* Technically to match a struct or union we need to check both |
1898 | 1892 | ways (src members vs. dst, dst members vs. src) but we make |
@@ -1902,7 +1896,8 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1902 | 1896 | This optimization can be defeated for unions, but is so |
1903 | 1897 | pathological as to render it irrelevant for our purposes. */ |
1904 | 1898 | |
1905 | - if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) | |
1899 | + if (dst_type != CTF_ERR && kind != CTF_K_FORWARD | |
1900 | + && dst_kind != CTF_K_FORWARD) | |
1906 | 1901 | { |
1907 | 1902 | if (ctf_type_size (src_fp, src_type) != |
1908 | 1903 | ctf_type_size (dst_fp, dst_type)) |
@@ -1936,6 +1931,10 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1936 | 1931 | dst.ctb_type = dst_type; |
1937 | 1932 | dst.ctb_dtd = dtd; |
1938 | 1933 | |
1934 | + /* Pre-emptively add this struct to the type mapping so that | |
1935 | + structures that refer to themselves work. */ | |
1936 | + ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type); | |
1937 | + | |
1939 | 1938 | if (ctf_member_iter (src_fp, src_type, membadd, &dst) != 0) |
1940 | 1939 | errs++; /* Increment errs and fail at bottom of case. */ |
1941 | 1940 |
@@ -1963,12 +1962,22 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1963 | 1962 | for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); |
1964 | 1963 | dmd != NULL; dmd = ctf_list_next (dmd)) |
1965 | 1964 | { |
1966 | - if ((dmd->dmd_type = ctf_add_type (dst_fp, src_fp, | |
1967 | - dmd->dmd_type)) == CTF_ERR) | |
1968 | - { | |
1969 | - if (ctf_errno (dst_fp) != ECTF_NONREPRESENTABLE) | |
1970 | - errs++; | |
1971 | - } | |
1965 | + ctf_file_t *dst = dst_fp; | |
1966 | + ctf_id_t memb_type; | |
1967 | + | |
1968 | + memb_type = ctf_type_mapping (src_fp, dmd->dmd_type, &dst); | |
1969 | + if (memb_type == 0) | |
1970 | + { | |
1971 | + if ((dmd->dmd_type = | |
1972 | + ctf_add_type_internal (dst_fp, src_fp, dmd->dmd_type, | |
1973 | + proc_tracking_fp)) == CTF_ERR) | |
1974 | + { | |
1975 | + if (ctf_errno (dst_fp) != ECTF_NONREPRESENTABLE) | |
1976 | + errs++; | |
1977 | + } | |
1978 | + } | |
1979 | + else | |
1980 | + dmd->dmd_type = memb_type; | |
1972 | 1981 | } |
1973 | 1982 | |
1974 | 1983 | if (errs) |
@@ -1977,7 +1986,8 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
1977 | 1986 | } |
1978 | 1987 | |
1979 | 1988 | case CTF_K_ENUM: |
1980 | - if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) | |
1989 | + if (dst_type != CTF_ERR && kind != CTF_K_FORWARD | |
1990 | + && dst_kind != CTF_K_FORWARD) | |
1981 | 1991 | { |
1982 | 1992 | if (ctf_enum_iter (src_fp, src_type, enumcmp, &dst) |
1983 | 1993 | || ctf_enum_iter (dst_fp, dst_type, enumcmp, &src)) |
@@ -2003,7 +2013,8 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
2003 | 2013 | |
2004 | 2014 | case CTF_K_TYPEDEF: |
2005 | 2015 | src_type = ctf_type_reference (src_fp, src_type); |
2006 | - src_type = ctf_add_type (dst_fp, src_fp, src_type); | |
2016 | + src_type = ctf_add_type_internal (dst_fp, src_fp, src_type, | |
2017 | + proc_tracking_fp); | |
2007 | 2018 | |
2008 | 2019 | if (src_type == CTF_ERR) |
2009 | 2020 | return CTF_ERR; /* errno is set for us. */ |
@@ -2017,9 +2028,8 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
2017 | 2028 | equivalent. */ |
2018 | 2029 | |
2019 | 2030 | if (dst_type == CTF_ERR) |
2020 | - { | |
2021 | 2031 | dst_type = ctf_add_typedef (dst_fp, flag, name, src_type); |
2022 | - } | |
2032 | + | |
2023 | 2033 | break; |
2024 | 2034 | |
2025 | 2035 | default: |
@@ -2031,6 +2041,27 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | ||
2031 | 2041 | return dst_type; |
2032 | 2042 | } |
2033 | 2043 | |
2044 | +ctf_id_t | |
2045 | +ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) | |
2046 | +{ | |
2047 | + ctf_id_t id; | |
2048 | + | |
2049 | + if (!src_fp->ctf_add_processing) | |
2050 | + src_fp->ctf_add_processing = ctf_dynhash_create (ctf_hash_integer, | |
2051 | + ctf_hash_eq_integer, | |
2052 | + NULL, NULL); | |
2053 | + | |
2054 | + /* We store the hash on the source, because it contains only source type IDs: | |
2055 | + but callers will invariably expect errors to appear on the dest. */ | |
2056 | + if (!src_fp->ctf_add_processing) | |
2057 | + return (ctf_set_errno (dst_fp, ENOMEM)); | |
2058 | + | |
2059 | + id = ctf_add_type_internal (dst_fp, src_fp, src_type, src_fp); | |
2060 | + ctf_dynhash_empty (src_fp->ctf_add_processing); | |
2061 | + | |
2062 | + return id; | |
2063 | +} | |
2064 | + | |
2034 | 2065 | /* Write the compressed CTF data stream to the specified gzFile descriptor. */ |
2035 | 2066 | int |
2036 | 2067 | ctf_gzwrite (ctf_file_t *fp, gzFile fd) |
@@ -294,6 +294,7 @@ struct ctf_file | ||
294 | 294 | /* Allow the caller to Change the name of link archive members. */ |
295 | 295 | ctf_link_memb_name_changer_f *ctf_link_memb_name_changer; |
296 | 296 | void *ctf_link_memb_name_changer_arg; /* Argument for it. */ |
297 | + ctf_dynhash_t *ctf_add_processing; /* Types ctf_add_type is working on now. */ | |
297 | 298 | char *ctf_tmp_typeslice; /* Storage for slicing up type names. */ |
298 | 299 | size_t ctf_tmp_typeslicelen; /* Size of the typeslice. */ |
299 | 300 | void *ctf_specific; /* Data for ctf_get/setspecific(). */ |
@@ -1665,6 +1665,7 @@ ctf_file_close (ctf_file_t *fp) | ||
1665 | 1665 | ctf_dynhash_destroy (fp->ctf_link_outputs); |
1666 | 1666 | ctf_dynhash_destroy (fp->ctf_link_type_mapping); |
1667 | 1667 | ctf_dynhash_destroy (fp->ctf_link_cu_mapping); |
1668 | + ctf_dynhash_destroy (fp->ctf_add_processing); | |
1668 | 1669 | |
1669 | 1670 | ctf_free (fp->ctf_sxlate); |
1670 | 1671 | ctf_free (fp->ctf_txlate); |