(root)/
binutils-2.41/
libctf/
testsuite/
libctf-writable/
error-propagation.c
       1  /* Make sure that errors are propagated properly from parent dicts to children
       2     when errors are encountered in child functions that can recurse to parents.
       3  
       4     We check specifically a subset of known-buggy functions.
       5     Functions that require a buggy linker to expose, or that only fail on
       6     assertion-failure-incurring corrupted dicts, are not tested. */
       7  
       8  #include <ctf-api.h>
       9  #include <stdio.h>
      10  #include <stdlib.h>
      11  #include <string.h>
      12  
      13  static const char *desc;
      14  
      15  static void
      16  check_prop_err (ctf_dict_t *child, ctf_dict_t *parent, int expected)
      17  {
      18    if (ctf_errno (child) == expected)
      19      return;
      20  
      21    if (ctf_errno (parent) == expected)
      22      fprintf (stderr, "%s: error propagation failure: error \"%s\" not seen on child, "
      23               "but instead on parent\n", desc, ctf_errmsg (ctf_errno (parent)));
      24    else
      25      fprintf (stderr, "%s: expected error is entirely lost: "
      26               "\"%s\" seen on parent, \"%s\" on child\n", desc,
      27               ctf_errmsg (ctf_errno (parent)),
      28               ctf_errmsg (ctf_errno (child)));
      29  }
      30  
      31  static void
      32  no_prop_err (void)
      33  {
      34    fprintf (stderr, "%s: expected error return not observed.\n", desc);
      35  }
      36  
      37  int main (void)
      38  {
      39    ctf_dict_t *parent;
      40    ctf_dict_t *blank;
      41    ctf_dict_t *child;
      42    ctf_id_t void_id;
      43    ctf_id_t base;
      44    ctf_id_t slice;
      45    ctf_id_t function;
      46    ctf_encoding_t long_encoding = { CTF_INT_SIGNED, 0, sizeof (long) };
      47    ctf_encoding_t void_encoding = { CTF_INT_SIGNED, 0, 0 };
      48    ctf_encoding_t foo;
      49    ctf_funcinfo_t fi;
      50    ctf_id_t bar;
      51    char *funcname;
      52    int err;
      53  
      54    if ((parent = ctf_create (&err)) == NULL
      55        || (child = ctf_create (&err)) == NULL
      56        || (blank = ctf_create (&err)) == NULL)
      57      {
      58        fprintf (stderr, "Cannot create dicts: %s\n", ctf_errmsg (err));
      59        return 1;
      60      }
      61  
      62    if ((ctf_import (child, parent)) < 0)
      63      {
      64        fprintf (stderr, "cannot import: %s\n", ctf_errmsg (ctf_errno (child)));
      65        return 1;
      66      }
      67  
      68    if ((void_id = ctf_add_integer (parent, CTF_ADD_ROOT, "void", &void_encoding))
      69        == CTF_ERR)
      70      goto parent_err;
      71  
      72    if ((base = ctf_add_integer (parent, CTF_ADD_ROOT, "long int", &long_encoding))
      73        == CTF_ERR)
      74      goto parent_err;
      75  
      76    foo.cte_format = 0;
      77    foo.cte_bits = 4;
      78    foo.cte_offset = 4;
      79    if ((slice = ctf_add_slice (child, CTF_ADD_ROOT, base, &foo)) == CTF_ERR)
      80      goto parent_err;
      81  
      82    if (ctf_add_variable (parent, "foo", base) < 0)
      83      goto child_err;
      84  
      85    fi.ctc_return = void_id;
      86    fi.ctc_argc = 0;
      87    fi.ctc_flags = 0;
      88    if ((function = ctf_add_function (child, CTF_ADD_ROOT, &fi, NULL)) == CTF_ERR)
      89      goto child_err;
      90  
      91    desc = "func info lookup of non-function";
      92    if ((ctf_func_type_info (child, base, &fi)) != CTF_ERR)
      93      no_prop_err ();
      94    check_prop_err (child, parent, ECTF_NOTFUNC);
      95  
      96    desc = "func args lookup of non-function";
      97    if ((ctf_func_type_args (child, base, 0, &bar)) != CTF_ERR)
      98      no_prop_err ();
      99    check_prop_err (child, parent, ECTF_NOTFUNC);
     100  
     101    if ((ctf_import (child, blank)) < 0)
     102      {
     103        fprintf (stderr, "cannot reimport: %s\n", ctf_errmsg (ctf_errno (child)));
     104        return 1;
     105      }
     106  
     107    /* This is testing ctf_type_resolve_unsliced(), which is called by the enum
     108       functions (which are not themselves buggy).  This typea isn't an enum, but
     109       that's OK: we're after an error, after all, and the type we're slicing is
     110       not visible any longer, so nothing can tell it's not an enum.  */
     111  
     112    desc = "child slice resolution";
     113    if ((ctf_enum_value (child, slice, "foo", NULL)) != CTF_ERR)
     114      no_prop_err ();
     115    check_prop_err (child, parent, ECTF_BADID);
     116  
     117    desc = "child slice encoding lookup";
     118    if ((ctf_type_encoding (child, slice, &foo)) != CTF_ERR)
     119      no_prop_err ();
     120    check_prop_err (child, parent, ECTF_BADID);
     121  
     122    desc = "func info lookup of non-function";
     123    if ((ctf_func_type_info (child, base, &fi)) != CTF_ERR)
     124      no_prop_err ();
     125    check_prop_err (child, parent, ECTF_BADID);
     126  
     127    desc = "func args lookup of non-function";
     128    if ((ctf_func_type_args (child, base, 0, &bar)) != CTF_ERR)
     129      no_prop_err ();
     130    check_prop_err (child, parent, ECTF_BADID);
     131  
     132    desc = "child slice addition";
     133    if ((slice = ctf_add_slice (child, CTF_ADD_ROOT, base, &foo)) != CTF_ERR)
     134      no_prop_err ();
     135    check_prop_err (child, parent, ECTF_BADID);
     136  
     137    desc = "variable lookup";
     138    if (ctf_lookup_variable (child, "foo") != CTF_ERR)
     139      no_prop_err ();
     140    check_prop_err (child, parent, ECTF_NOTYPEDAT);
     141  
     142    desc = "function lookup via ctf_type_aname";
     143    if ((funcname = ctf_type_aname (child, function)) != NULL)
     144      {
     145        no_prop_err ();
     146        free (funcname);
     147      }
     148    check_prop_err (child, parent, ECTF_BADID);
     149  
     150    ctf_dict_close (child);
     151    ctf_dict_close (parent);
     152    ctf_dict_close (blank);
     153    fprintf (stderr, "All done.\n");
     154    return 0;
     155  
     156   parent_err:
     157    fprintf (stderr, "cannot populate parent: %s\n", ctf_errmsg (ctf_errno (parent)));
     158    return 1;
     159  
     160   child_err:
     161    fprintf (stderr, "cannot populate child: %s\n", ctf_errmsg (ctf_errno (parent)));
     162    return 1;
     163  
     164  }