aboutsummaryrefslogtreecommitdiff
path: root/libctf/testsuite/libctf-lookup/enum-symbol.c
blob: 4f63b61b8039acb24aa7b0849028af789bac4292 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "config.h"
#include <bfd.h>
#include <elf.h>
#include <ctf-api.h>
#include <swap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

ssize_t symidx_64 (ctf_sect_t *s, ctf_sect_t *strsect, int little_endian, const char *name)
{
  const char *strs = (const char *) strsect->cts_data;
  size_t i;
  Elf64_Sym *sym = (Elf64_Sym *) s->cts_data;
  for (i = 0; i < s->cts_size / s->cts_entsize; i++, sym++)
    {
      Elf64_Word nameoff = sym->st_name;
#ifdef WORDS_BIGENDIAN
      if (little_endian)
	swap_thing (nameoff);
#else
      if (!little_endian)
	swap_thing (nameoff);
#endif
      if (strcmp (strs + nameoff, name) == 0)
	return i;
    }
  return -1;
}

ssize_t symidx_32 (ctf_sect_t *s, ctf_sect_t *strsect, int little_endian, const char *name)
{
  const char *strs = (const char *) strsect->cts_data;
  size_t i;
  Elf32_Sym *sym = (Elf32_Sym *) s->cts_data;
  for (i = 0; i < s->cts_size / s->cts_entsize; i++, sym++)
    {
      Elf32_Word nameoff = sym->st_name;
#ifdef WORDS_BIGENDIAN
      if (little_endian)
	swap_thing (nameoff);
#else
      if (!little_endian)
	swap_thing (nameoff);
#endif
      if (strcmp (strs + nameoff, name) == 0)
	return i;
    }
  return -1;
}

int
main (int argc, char *argv[])
{
  ctf_dict_t *fp;
  bfd *abfd;
  ctf_archive_t *ctf;
  ctf_sect_t symsect;
  ctf_sect_t strsect;
  ssize_t symidx;
  int err;
  ctf_id_t type;
  ctf_next_t *i = NULL;
  const char *name;
  int val;
  int little_endian;

  ssize_t (*get_sym) (ctf_sect_t *s, ctf_sect_t *strsect, int little_endian, const char *name);

  if (argc != 2)
    {
      fprintf (stderr, "Syntax: %s PROGRAM\n", argv[0]);
      exit(1);
    }

  /* Figure out the endianness of the symtab(s).  */
  if ((abfd = bfd_openr (argv[1], NULL)) == NULL
      || !bfd_check_format (abfd, bfd_object))
    goto bfd_open_err;
  little_endian = bfd_little_endian (abfd);
  bfd_close_all_done (abfd);

  if ((ctf = ctf_open (argv[1], NULL, &err)) == NULL)
    goto open_err;

  if ((fp = ctf_dict_open (ctf, NULL, &err)) == NULL)
    goto open_err;

  symsect = ctf_getsymsect (fp);
  strsect = ctf_getstrsect (fp);
  if (symsect.cts_data == NULL
      || strsect.cts_data == NULL)
    {
      fprintf (stderr, "%s: no symtab or strtab\n", argv[0]);
      return 1;
    }

  ctf_dict_close (fp);

  if (symsect.cts_entsize != sizeof (Elf64_Sym) &&
      symsect.cts_entsize != sizeof (Elf32_Sym))
    {
      fprintf (stderr, "%s: unknown symsize: %lx\n", argv[0],
	       symsect.cts_size);
      return 1;
    }

  switch (symsect.cts_entsize)
    {
    case sizeof (Elf64_Sym): get_sym = symidx_64; break;
    case sizeof (Elf32_Sym): get_sym = symidx_32; break;
    }

  if ((symidx = get_sym (&symsect, &strsect, little_endian, "primary1")) < 0)
    {
      fprintf (stderr, "%s: symbol not found: primary1\n", argv[0]);
      return 1;
    }

  /* Fish it out, then fish out all its enumerand/value pairs.  */

  if ((fp = ctf_arc_lookup_symbol (ctf, symidx, &type, &err)) == NULL)
    goto sym_err;

  while ((name = ctf_enum_next (fp, type, &i, &val)) != NULL)
    {
      printf ("%s has value %i\n", name, val);
    }
  if (ctf_errno (fp) != ECTF_NEXT_END)
    goto nerr;

  ctf_dict_close (fp);
  ctf_close (ctf);

  return 0;

 bfd_open_err:
  fprintf (stderr, "%s: cannot open: %s\n", argv[0], bfd_errmsg (bfd_get_error ()));
  return 1;

 open_err:
  fprintf (stderr, "%s: cannot open: %s\n", argv[0], ctf_errmsg (err));
  return 1;
 sym_err:
  fprintf (stderr, "%s: Symbol lookup error: %s\n", argv[0], ctf_errmsg (err));
  return 1;
 err:
  fprintf (stderr, "Lookup failed: %s\n", ctf_errmsg (ctf_errno (fp)));
  return 1;
 nerr:
  fprintf (stderr, "iteration failed: %s\n", ctf_errmsg (ctf_errno (fp)));
  return 1;
}