1  /* Make sure that writing out a dict with a symtypetab without going via
       2     ctf_link_write (as a compiler might do to generate input destined for a
       3     linker) always writes out a complete indexed, sorted symtypetab, ignoring the
       4     set of symbols reported (if any).  Also a test of dynamic dict sym
       5     iteration.  */
       6  
       7  #include <ctf-api.h>
       8  #include <stdio.h>
       9  #include <stdlib.h>
      10  #include <string.h>
      11  
      12  static int
      13  report_sym (ctf_dict_t *fp, ctf_link_sym_t *sym, const char *name,
      14  	    uint32_t idx, uint32_t st_type)
      15  {
      16    sym->st_name = name;
      17    sym->st_symidx = idx;
      18    sym->st_type = st_type;
      19    return ctf_link_add_linker_symbol (fp, sym);
      20  }
      21  
      22  static void
      23  try_maybe_reporting (int report)
      24  {
      25    ctf_dict_t *fp;
      26    ctf_id_t func, func2, func3, base, base2, base3;
      27    ctf_encoding_t e = { CTF_INT_SIGNED, 0, sizeof (long) };
      28    ctf_id_t dummy;
      29    ctf_funcinfo_t fi;
      30    ctf_next_t *i = NULL;
      31    ctf_id_t symtype;
      32    const char *symname;
      33    unsigned char *buf;
      34    size_t bufsiz;
      35    int err;
      36  
      37    if ((fp = ctf_create (&err)) == NULL)
      38      goto create_err;
      39  
      40    /* Add a couple of sets of types to hang symbols off.  We use multiple
      41       identical types so we can distinguish between distinct func / data symbols
      42       later on.  */
      43  
      44    if (((base = ctf_add_integer (fp, CTF_ADD_ROOT, "long int", &e)) == CTF_ERR) ||
      45        ((base2 = ctf_add_integer (fp, CTF_ADD_ROOT, "long int", &e)) == CTF_ERR) ||
      46        ((base3 = ctf_add_integer (fp, CTF_ADD_ROOT, "long int", &e)) == CTF_ERR))
      47        goto create_types_err;
      48  
      49    fi.ctc_return = base;
      50    fi.ctc_argc = 0;
      51    fi.ctc_flags = 0;
      52    if (((func = ctf_add_function (fp, CTF_ADD_ROOT, &fi, &dummy)) == CTF_ERR) ||
      53        ((func2 = ctf_add_function (fp, CTF_ADD_ROOT, &fi, &dummy)) == CTF_ERR) ||
      54        ((func3 = ctf_add_function (fp, CTF_ADD_ROOT, &fi, &dummy)) == CTF_ERR))
      55      goto create_types_err;
      56  
      57    /* Add some function and data symbols.  We intentionally add the symbols in
      58       near-inverse order by symbol name, so that we can tell whether the
      59       (necessarily indexed) section was sorted (since the sort is always in
      60       lexicographical sort ordef by name).  */
      61    if ((ctf_add_objt_sym (fp, "data_c", base) < 0) ||
      62        (ctf_add_objt_sym (fp, "data_a", base2) < 0) ||
      63        (ctf_add_objt_sym (fp, "data_b", base3) < 0))
      64      goto create_syms_err;
      65  
      66    if ((ctf_add_func_sym (fp, "func_c", func) < 0) ||
      67        (ctf_add_func_sym (fp, "func_a", func2) < 0) ||
      68        (ctf_add_func_sym (fp, "func_b", func3) < 0))
      69      goto create_syms_err;
      70  
      71    /* Make sure we can iterate over them in a dynamic dict and that they have the
      72       right types.  We don't care about their order at this stage, which makes
      73       the validation here a bit more verbose than it is below.  */
      74  
      75    while ((symtype = ctf_symbol_next (fp, &i, &symname, 0)) != CTF_ERR)
      76      {
      77        if (symtype == base && strcmp (symname, "data_c") == 0)
      78  	continue;
      79        if (symtype == base2 && strcmp (symname, "data_a") == 0)
      80  	continue;
      81        if (symtype == base3 && strcmp (symname, "data_b") == 0)
      82  	continue;
      83        goto iter_compar_err;
      84      }
      85    if (ctf_errno (fp) != ECTF_NEXT_END)
      86      goto iter_err;
      87  
      88    while ((symtype = ctf_symbol_next (fp, &i, &symname, 1)) != CTF_ERR)
      89      {
      90        if (symtype == func && strcmp (symname, "func_c") == 0)
      91  	continue;
      92        if (symtype == func2 && strcmp (symname, "func_a") == 0)
      93  	continue;
      94        if (symtype == func3 && strcmp (symname, "func_b") == 0)
      95  	continue;
      96        goto iter_compar_err;
      97      }
      98    if (ctf_errno (fp) != ECTF_NEXT_END)
      99      goto iter_err;
     100  
     101    /* Look up all the symbols by name and make sure that works.  */
     102  
     103    if (ctf_lookup_by_symbol_name (fp, "data_a") != base2)
     104      goto lookup_syms_err;
     105    if (ctf_lookup_by_symbol_name (fp, "data_b") != base3)
     106      goto lookup_syms_err;
     107    if (ctf_lookup_by_symbol_name (fp, "data_c") != base)
     108      goto lookup_syms_err;
     109    if (ctf_lookup_by_symbol_name (fp, "func_a") != func2)
     110      goto lookup_syms_err;
     111    if (ctf_lookup_by_symbol_name (fp, "func_b") != func3)
     112      goto lookup_syms_err;
     113    if (ctf_lookup_by_symbol_name (fp, "func_c") != func)
     114      goto lookup_syms_err;
     115  
     116    /* Possibly report some but not all of the symbols, as if we are a linker (no
     117       real program would do this without using the ctf_link APIs, but it's not
     118       *prohibited*, just useless, and if they do we don't want things to
     119       break.  In particular we want all the symbols written out, reported or no,
     120       ignoring the reported symbol set entirely.)  */
     121    if (report)
     122      {
     123        ctf_link_sym_t sym;
     124        sym.st_nameidx_set = 0;
     125        sym.st_nameidx = 0;
     126        sym.st_shndx = 404; /* Arbitrary, not SHN_UNDEF or SHN_EXTABS.  */
     127        sym.st_value = 404; /* Arbitrary, nonzero.  */
     128  
     129        /* STT_OBJECT: 1.  Don't rely on the #define being visible: this may be a
     130  	 non-ELF platform!  */
     131        if (report_sym (fp, &sym, "data_c", 2, 1) < 0 ||
     132  	  report_sym (fp, &sym, "data_a", 3, 1) < 0)
     133  	goto report_err;
     134  
     135        /* STT_FUNC: 2.  */
     136        if (report_sym (fp, &sym, "func_c", 4, 2) < 0 ||
     137  	  report_sym (fp, &sym, "func_a", 5, 2) < 0)
     138  	goto report_err;
     139  
     140        /* Look up all the symbols by name now we have reported symbols.  */
     141  
     142        if (ctf_lookup_by_symbol_name (fp, "data_a") != base2)
     143  	goto lookup_syms_err;
     144        if (ctf_lookup_by_symbol_name (fp, "data_b") != base3)
     145  	goto lookup_syms_err;
     146        if (ctf_lookup_by_symbol_name (fp, "data_c") != base)
     147  	goto lookup_syms_err;
     148        if (ctf_lookup_by_symbol_name (fp, "func_a") != func2)
     149  	goto lookup_syms_err;
     150        if (ctf_lookup_by_symbol_name (fp, "func_b") != func3)
     151  	goto lookup_syms_err;
     152        if (ctf_lookup_by_symbol_name (fp, "func_c") != func)
     153  	goto lookup_syms_err;
     154      }
     155  
     156    /* Write out, to memory.  */
     157  
     158    if ((buf = ctf_write_mem (fp, &bufsiz, 4096)) == NULL)
     159      goto write_err;
     160    ctf_file_close (fp);
     161  
     162    /* Read back in.  */
     163    if ((fp = ctf_simple_open ((const char *) buf, bufsiz, NULL, 0, 0, NULL,
     164  			     0, &err)) == NULL)
     165      goto open_err;
     166  
     167    /* Verify symbol order against the order we expect if this dict is sorted and
     168       indexed.  */
     169  
     170    struct ctf_symtype_expected
     171    {
     172      const char *name;
     173      ctf_id_t id;
     174    } *expected;
     175    struct ctf_symtype_expected expected_obj[] = { { "data_a", base2 },
     176  						 { "data_b", base3 },
     177  						 { "data_c", base },
     178  						 { NULL, 0 } };
     179    struct ctf_symtype_expected expected_func[] = { { "func_a", func2 },
     180  						  { "func_b", func3 },
     181  						  { "func_c", func },
     182  						  { NULL, 0 } };
     183    expected = expected_obj;
     184  
     185    while ((symtype = ctf_symbol_next (fp, &i, &symname, 0)) != CTF_ERR)
     186      {
     187        if (expected == NULL)
     188  	goto expected_overshoot_err;
     189        if (symtype != expected->id || strcmp (symname, expected->name) != 0)
     190  	goto expected_compar_err;
     191        printf ("Seen: %s\n", symname);
     192        expected++;
     193      }
     194  
     195    expected = expected_func;
     196    while ((symtype = ctf_symbol_next (fp, &i, &symname, 1)) != CTF_ERR)
     197      {
     198        if (expected == NULL)
     199  	goto expected_overshoot_err;
     200        if (symtype != expected->id || strcmp (symname, expected->name) != 0)
     201  	goto expected_compar_err;
     202        printf ("Seen: %s\n", symname);
     203        expected++;
     204      }
     205  
     206    ctf_file_close (fp);
     207    free (buf);
     208  
     209    return;
     210  
     211   create_err:
     212    fprintf (stderr, "Creation failed: %s\n", ctf_errmsg (err));
     213    exit (1);
     214   open_err:
     215    fprintf (stderr, "Reopen failed: %s\n", ctf_errmsg (err));
     216    exit (1);
     217   create_types_err:
     218    fprintf (stderr, "Cannot create types: %s\n", ctf_errmsg (ctf_errno (fp)));
     219    exit (1);
     220   create_syms_err:
     221    fprintf (stderr, "Cannot create syms: %s\n", ctf_errmsg (ctf_errno (fp)));
     222    exit (1);
     223   iter_compar_err:
     224    fprintf (stderr, "Dynamic iteration comparison failure: %s "
     225  	   "(reported type: %lx)\n", symname, symtype);
     226    exit (1);
     227   iter_err:
     228    fprintf (stderr, "Cannot iterate: %s\n", ctf_errmsg (ctf_errno (fp)));
     229    exit (1);
     230   report_err:
     231    fprintf (stderr, "Cannot report symbol: %s\n", ctf_errmsg (ctf_errno (fp)));
     232    exit (1);
     233   write_err:
     234    fprintf (stderr, "Cannot write out: %s\n", ctf_errmsg (ctf_errno (fp)));
     235    exit (1);
     236   expected_overshoot_err:
     237    fprintf (stderr, "Too many symbols in post-writeout comparison\n");
     238    exit (1);
     239   lookup_syms_err:
     240    fprintf (stderr, "Explicit lookup of symbols by name failed: %s\n",
     241  	   ctf_errmsg (ctf_errno (fp)));
     242    exit (1);
     243   expected_compar_err:
     244    fprintf (stderr, "Non-dynamic iteration comparison failure: %s "
     245  	   "(type %lx): expected %s (type %lx)\n", symname, symtype,
     246  	   expected->name, expected->id);
     247    exit (1);
     248  }
     249  
     250  int
     251  main (int argc, char *argv[])
     252  {
     253    try_maybe_reporting (0);
     254    try_maybe_reporting (1);
     255  }