1 /* Symbol, variable and name lookup.
2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
4 This file is part of libctf.
6 libctf is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not see
18 <http://www.gnu.org/licenses/>. */
24 /* Compare the given input string and length against a table of known C storage
25 qualifier keywords. We just ignore these in ctf_lookup_by_name, below. To
26 do this quickly, we use a pre-computed Perfect Hash Function similar to the
27 technique originally described in the classic paper:
29 R.J. Cichelli, "Minimal Perfect Hash Functions Made Simple",
30 Communications of the ACM, Volume 23, Issue 1, January 1980, pp. 17-19.
32 For an input string S of length N, we use hash H = S[N - 1] + N - 105, which
33 for the current set of qualifiers yields a unique H in the range [0 .. 20].
34 The hash can be modified when the keyword set changes as necessary. We also
35 store the length of each keyword and check it prior to the final strcmp().
37 TODO: just use gperf. */
40 isqualifier (const char *s
, size_t len
)
42 static const struct qual
47 {"static", 6}, {"", 0}, {"", 0}, {"", 0},
48 {"volatile", 8}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
49 {"", 0}, {"auto", 4}, {"extern", 6}, {"", 0}, {"", 0},
50 {"", 0}, {"", 0}, {"const", 5}, {"register", 8},
51 {"", 0}, {"restrict", 8}, {"_Restrict", 9}
54 int h
= s
[len
- 1] + (int) len
- 105;
55 const struct qual
*qp
= &qhash
[h
];
57 return (h
>= 0 && (size_t) h
< sizeof (qhash
) / sizeof (qhash
[0])
58 && (size_t) len
== qp
->q_len
&&
59 strncmp (qp
->q_name
, s
, qp
->q_len
) == 0);
62 /* Attempt to convert the given C type name into the corresponding CTF type ID.
63 It is not possible to do complete and proper conversion of type names
64 without implementing a more full-fledged parser, which is necessary to
65 handle things like types that are function pointers to functions that
66 have arguments that are function pointers, and fun stuff like that.
67 Instead, this function implements a very simple conversion algorithm that
68 finds the things that we actually care about: structs, unions, enums,
69 integers, floats, typedefs, and pointers to any of these named types. */
72 ctf_lookup_by_name (ctf_file_t
*fp
, const char *name
)
74 static const char delimiters
[] = " \t\n\r\v\f*";
76 const ctf_lookup_t
*lp
;
77 const char *p
, *q
, *end
;
79 ctf_id_t ntype
, ptype
;
82 return (ctf_set_errno (fp
, EINVAL
));
84 for (p
= name
, end
= name
+ strlen (name
); *p
!= '\0'; p
= q
)
86 while (isspace ((int) *p
))
87 p
++; /* Skip leading whitespace. */
92 if ((q
= strpbrk (p
+ 1, delimiters
)) == NULL
)
93 q
= end
; /* Compare until end. */
97 /* Find a pointer to type by looking in fp->ctf_ptrtab.
98 If we can't find a pointer to the given type, see if
99 we can compute a pointer to the type resulting from
100 resolving the type down to its base type and use
101 that instead. This helps with cases where the CTF
102 data includes "struct foo *" but not "foo_t *" and
103 the user tries to access "foo_t *" in the debugger.
105 TODO need to handle parent containers too. */
107 ntype
= fp
->ctf_ptrtab
[LCTF_TYPE_TO_INDEX (fp
, type
)];
110 ntype
= ctf_type_resolve_unsliced (fp
, type
);
113 fp
->ctf_ptrtab
[LCTF_TYPE_TO_INDEX (fp
, ntype
)]) == 0)
115 (void) ctf_set_errno (fp
, ECTF_NOTYPE
);
120 type
= LCTF_INDEX_TO_TYPE (fp
, ntype
, (fp
->ctf_flags
& LCTF_CHILD
));
126 if (isqualifier (p
, (size_t) (q
- p
)))
127 continue; /* Skip qualifier keyword. */
129 for (lp
= fp
->ctf_lookups
; lp
->ctl_prefix
!= NULL
; lp
++)
131 /* TODO: This is not MT-safe. */
132 if ((lp
->ctl_prefix
[0] == '\0' ||
133 strncmp (p
, lp
->ctl_prefix
, (size_t) (q
- p
)) == 0) &&
134 (size_t) (q
- p
) >= lp
->ctl_len
)
136 for (p
+= lp
->ctl_len
; isspace ((int) *p
); p
++)
137 continue; /* Skip prefix and next whitespace. */
139 if ((q
= strchr (p
, '*')) == NULL
)
140 q
= end
; /* Compare until end. */
142 while (isspace ((int) q
[-1]))
143 q
--; /* Exclude trailing whitespace. */
145 /* Expand and/or allocate storage for a slice of the name, then
148 if (fp
->ctf_tmp_typeslicelen
>= (size_t) (q
- p
) + 1)
150 memcpy (fp
->ctf_tmp_typeslice
, p
, (size_t) (q
- p
));
151 fp
->ctf_tmp_typeslice
[(size_t) (q
- p
)] = '\0';
155 free (fp
->ctf_tmp_typeslice
);
156 fp
->ctf_tmp_typeslice
= xstrndup (p
, (size_t) (q
- p
));
157 if (fp
->ctf_tmp_typeslice
== NULL
)
159 (void) ctf_set_errno (fp
, ENOMEM
);
164 if ((type
= ctf_lookup_by_rawhash (fp
, lp
->ctl_hash
,
165 fp
->ctf_tmp_typeslice
)) == 0)
167 (void) ctf_set_errno (fp
, ECTF_NOTYPE
);
175 if (lp
->ctl_prefix
== NULL
)
177 (void) ctf_set_errno (fp
, ECTF_NOTYPE
);
182 if (*p
!= '\0' || type
== 0)
183 return (ctf_set_errno (fp
, ECTF_SYNTAX
));
188 if (fp
->ctf_parent
!= NULL
189 && (ptype
= ctf_lookup_by_name (fp
->ctf_parent
, name
)) != CTF_ERR
)
195 typedef struct ctf_lookup_var_key
198 const char *clvk_name
;
199 } ctf_lookup_var_key_t
;
201 /* A bsearch function for variable names. */
204 ctf_lookup_var (const void *key_
, const void *memb_
)
206 const ctf_lookup_var_key_t
*key
= key_
;
207 const ctf_varent_t
*memb
= memb_
;
209 return (strcmp (key
->clvk_name
, ctf_strptr (key
->clvk_fp
, memb
->ctv_name
)));
212 /* Given a variable name, return the type of the variable with that name. */
215 ctf_lookup_variable (ctf_file_t
*fp
, const char *name
)
218 ctf_lookup_var_key_t key
= { fp
, name
};
220 /* This array is sorted, so we can bsearch for it. */
222 ent
= bsearch (&key
, fp
->ctf_vars
, fp
->ctf_nvars
, sizeof (ctf_varent_t
),
227 if (fp
->ctf_parent
!= NULL
)
228 return ctf_lookup_variable (fp
->ctf_parent
, name
);
230 return (ctf_set_errno (fp
, ECTF_NOTYPEDAT
));
233 return ent
->ctv_type
;
236 /* Given a symbol table index, return the name of that symbol from the secondary
237 string table, or the null string (never NULL). */
239 ctf_lookup_symbol_name (ctf_file_t
*fp
, unsigned long symidx
)
241 const ctf_sect_t
*sp
= &fp
->ctf_symtab
;
244 if (sp
->cts_data
== NULL
)
246 ctf_set_errno (fp
, ECTF_NOSYMTAB
);
250 if (symidx
>= fp
->ctf_nsyms
)
252 ctf_set_errno (fp
, EINVAL
);
256 if (sp
->cts_entsize
== sizeof (Elf32_Sym
))
258 const Elf32_Sym
*symp
= (Elf32_Sym
*) sp
->cts_data
+ symidx
;
259 gsp
= ctf_sym_to_elf64 (symp
, &sym
);
262 gsp
= (Elf64_Sym
*) sp
->cts_data
+ symidx
;
264 if (gsp
->st_name
< fp
->ctf_str
[CTF_STRTAB_1
].cts_len
)
265 return (const char *) fp
->ctf_str
[CTF_STRTAB_1
].cts_strs
+ gsp
->st_name
;
270 /* Given a symbol table index, return the type of the data object described
271 by the corresponding entry in the symbol table. */
274 ctf_lookup_by_symbol (ctf_file_t
*fp
, unsigned long symidx
)
276 const ctf_sect_t
*sp
= &fp
->ctf_symtab
;
279 if (sp
->cts_data
== NULL
)
280 return (ctf_set_errno (fp
, ECTF_NOSYMTAB
));
282 if (symidx
>= fp
->ctf_nsyms
)
283 return (ctf_set_errno (fp
, EINVAL
));
285 if (sp
->cts_entsize
== sizeof (Elf32_Sym
))
287 const Elf32_Sym
*symp
= (Elf32_Sym
*) sp
->cts_data
+ symidx
;
288 if (ELF32_ST_TYPE (symp
->st_info
) != STT_OBJECT
)
289 return (ctf_set_errno (fp
, ECTF_NOTDATA
));
293 const Elf64_Sym
*symp
= (Elf64_Sym
*) sp
->cts_data
+ symidx
;
294 if (ELF64_ST_TYPE (symp
->st_info
) != STT_OBJECT
)
295 return (ctf_set_errno (fp
, ECTF_NOTDATA
));
298 if (fp
->ctf_sxlate
[symidx
] == -1u)
299 return (ctf_set_errno (fp
, ECTF_NOTYPEDAT
));
301 type
= *(uint32_t *) ((uintptr_t) fp
->ctf_buf
+ fp
->ctf_sxlate
[symidx
]);
303 return (ctf_set_errno (fp
, ECTF_NOTYPEDAT
));
308 /* Return the native dict of a given type: if called on a child and the
309 type is in the parent, return the parent. Needed if you plan to access
310 the type directly, without using the API. */
312 ctf_get_dict (ctf_file_t
*fp
, ctf_id_t type
)
314 if ((fp
->ctf_flags
& LCTF_CHILD
) && LCTF_TYPE_ISPARENT (fp
, type
))
315 return fp
->ctf_parent
;
320 /* Return the pointer to the internal CTF type data corresponding to the
321 given type ID. If the ID is invalid, the function returns NULL.
322 This function is not exported outside of the library. */
325 ctf_lookup_by_id (ctf_file_t
**fpp
, ctf_id_t type
)
327 ctf_file_t
*fp
= *fpp
; /* Caller passes in starting CTF dict. */
330 if ((fp
= ctf_get_dict (fp
, type
)) == NULL
)
332 (void) ctf_set_errno (*fpp
, ECTF_NOPARENT
);
336 /* If this dict is writable, check for a dynamic type. */
338 if (fp
->ctf_flags
& LCTF_RDWR
)
342 if ((dtd
= ctf_dynamic_type (fp
, type
)) != NULL
)
345 return &dtd
->dtd_data
;
347 (void) ctf_set_errno (*fpp
, ECTF_BADID
);
351 /* Check for a type in the static portion. */
353 idx
= LCTF_TYPE_TO_INDEX (fp
, type
);
354 if (idx
> 0 && (unsigned long) idx
<= fp
->ctf_typemax
)
356 *fpp
= fp
; /* Function returns ending CTF container. */
357 return (LCTF_INDEX_TO_TYPEPTR (fp
, idx
));
360 (void) ctf_set_errno (*fpp
, ECTF_BADID
);
364 /* Given a symbol table index, return the info for the function described
365 by the corresponding entry in the symbol table. */
368 ctf_func_info (ctf_file_t
*fp
, unsigned long symidx
, ctf_funcinfo_t
*fip
)
370 const ctf_sect_t
*sp
= &fp
->ctf_symtab
;
372 uint32_t info
, kind
, n
;
374 if (sp
->cts_data
== NULL
)
375 return (ctf_set_errno (fp
, ECTF_NOSYMTAB
));
377 if (symidx
>= fp
->ctf_nsyms
)
378 return (ctf_set_errno (fp
, EINVAL
));
380 if (sp
->cts_entsize
== sizeof (Elf32_Sym
))
382 const Elf32_Sym
*symp
= (Elf32_Sym
*) sp
->cts_data
+ symidx
;
383 if (ELF32_ST_TYPE (symp
->st_info
) != STT_FUNC
)
384 return (ctf_set_errno (fp
, ECTF_NOTFUNC
));
388 const Elf64_Sym
*symp
= (Elf64_Sym
*) sp
->cts_data
+ symidx
;
389 if (ELF64_ST_TYPE (symp
->st_info
) != STT_FUNC
)
390 return (ctf_set_errno (fp
, ECTF_NOTFUNC
));
393 if (fp
->ctf_sxlate
[symidx
] == -1u)
394 return (ctf_set_errno (fp
, ECTF_NOFUNCDAT
));
396 dp
= (uint32_t *) ((uintptr_t) fp
->ctf_buf
+ fp
->ctf_sxlate
[symidx
]);
399 kind
= LCTF_INFO_KIND (fp
, info
);
400 n
= LCTF_INFO_VLEN (fp
, info
);
402 if (kind
== CTF_K_UNKNOWN
&& n
== 0)
403 return (ctf_set_errno (fp
, ECTF_NOFUNCDAT
));
405 if (kind
!= CTF_K_FUNCTION
)
406 return (ctf_set_errno (fp
, ECTF_CORRUPT
));
408 fip
->ctc_return
= *dp
++;
412 if (n
!= 0 && dp
[n
- 1] == 0)
414 fip
->ctc_flags
|= CTF_FUNC_VARARG
;
421 /* Given a symbol table index, return the arguments for the function described
422 by the corresponding entry in the symbol table. */
425 ctf_func_args (ctf_file_t
* fp
, unsigned long symidx
, uint32_t argc
,
431 if (ctf_func_info (fp
, symidx
, &f
) < 0)
432 return -1; /* errno is set for us. */
434 /* The argument data is two uint32_t's past the translation table
435 offset: one for the function info, and one for the return type. */
437 dp
= (uint32_t *) ((uintptr_t) fp
->ctf_buf
+ fp
->ctf_sxlate
[symidx
]) + 2;
439 for (argc
= MIN (argc
, f
.ctc_argc
); argc
!= 0; argc
--)