From: Nick Alcock Date: Tue, 23 Apr 2019 20:45:30 +0000 (+0100) Subject: libctf: low-level list manipulation and helper utilities X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=94585e7f93c9477bcf2835d8245e967053ce2b41;p=deliverable%2Fbinutils-gdb.git libctf: low-level list manipulation and helper utilities These utilities are a bit of a ragbag of small things needed by more than one TU: list manipulation, ELF32->64 translators, routines to look up strings in string tables, dynamically-allocated string appenders, and routines to set the specialized errno values previously committed in . We do still need to dig around in raw ELF symbol tables in places, because libctf allows the caller to pass in the contents of string and symbol sections without telling it where they come from, so we cannot use BFD to get the symbols (BFD reasonably demands the entire file). So extract minimal ELF definitions from glibc into a private header named libctf/elf.h: later, we use those to get symbols. (The start-of- copyright range on elf.h reflects this glibc heritage.) libctf/ * ctf-util.c: New file. * elf.h: Likewise. * ctf-impl.h: Include it, and add declarations. --- diff --git a/libctf/ChangeLog b/libctf/ChangeLog index 6a37212d8b..7648c268ce 100644 --- a/libctf/ChangeLog +++ b/libctf/ChangeLog @@ -1,3 +1,9 @@ +2019-05-28 Nick Alcock + + * ctf-util.c: New file. + * elf.h: Likewise. + * ctf-impl.h: Include it, and add declarations. + 2019-05-28 Nick Alcock * ctf-impl.h: New file. diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h index 4356a2a9f0..268b2f343f 100644 --- a/libctf/ctf-impl.h +++ b/libctf/ctf-impl.h @@ -24,6 +24,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" @@ -51,6 +58,25 @@ extern "C" #endif +typedef struct ctf_list +{ + struct ctf_list *l_prev; /* Previous pointer or tail pointer. */ + struct ctf_list *l_next; /* Next pointer or head pointer. */ +} ctf_list_t; + +#define ctf_list_prev(elem) ((void *)(((ctf_list_t *)(elem))->l_prev)) +#define ctf_list_next(elem) ((void *)(((ctf_list_t *)(elem))->l_next)) + +extern void ctf_list_append (ctf_list_t *, void *); +extern void ctf_list_prepend (ctf_list_t *, void *); +extern void ctf_list_delete (ctf_list_t *, void *); + +extern const char *ctf_strraw (ctf_file_t *, uint32_t); +extern const char *ctf_strptr (ctf_file_t *, uint32_t); + +extern void *ctf_set_open_errno (int *, int); +extern long ctf_set_errno (ctf_file_t *, int); + _libctf_malloc_ extern void *ctf_data_alloc (size_t); extern void ctf_data_free (void *, size_t); @@ -65,10 +91,17 @@ _libctf_malloc_ extern void *ctf_alloc (size_t); extern void ctf_free (void *); +_libctf_malloc_ +extern char *ctf_strdup (const char *); +extern char *ctf_str_append (char *, const char *); +extern const char *ctf_strerror (int); + _libctf_printflike_ (1, 2) extern void ctf_dprintf (const char *, ...); extern void libctf_init_debug (void); +extern Elf64_Sym *ctf_sym_to_elf64 (const Elf32_Sym *src, Elf64_Sym *dst); + extern int _libctf_debug; /* debugging messages enabled */ #ifdef __cplusplus diff --git a/libctf/ctf-util.c b/libctf/ctf-util.c new file mode 100644 index 0000000000..44600467a7 --- /dev/null +++ b/libctf/ctf-util.c @@ -0,0 +1,176 @@ +/* Miscellaneous utilities. + Copyright (C) 2019 Free Software Foundation, Inc. + + This file is part of libctf. + + libctf is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not see + . */ + +#include +#include + +/* Simple doubly-linked list append routine. This implementation assumes that + each list element contains an embedded ctf_list_t as the first member. + An additional ctf_list_t is used to store the head (l_next) and tail + (l_prev) pointers. The current head and tail list elements have their + previous and next pointers set to NULL, respectively. */ + +void +ctf_list_append (ctf_list_t *lp, void *newp) +{ + ctf_list_t *p = lp->l_prev; /* p = tail list element. */ + ctf_list_t *q = newp; /* q = new list element. */ + + lp->l_prev = q; + q->l_prev = p; + q->l_next = NULL; + + if (p != NULL) + p->l_next = q; + else + lp->l_next = q; +} + +/* Prepend the specified existing element to the given ctf_list_t. The + existing pointer should be pointing at a struct with embedded ctf_list_t. */ + +void +ctf_list_prepend (ctf_list_t * lp, void *newp) +{ + ctf_list_t *p = newp; /* p = new list element. */ + ctf_list_t *q = lp->l_next; /* q = head list element. */ + + lp->l_next = p; + p->l_prev = NULL; + p->l_next = q; + + if (q != NULL) + q->l_prev = p; + else + lp->l_prev = p; +} + +/* Delete the specified existing element from the given ctf_list_t. The + existing pointer should be pointing at a struct with embedded ctf_list_t. */ + +void +ctf_list_delete (ctf_list_t *lp, void *existing) +{ + ctf_list_t *p = existing; + + if (p->l_prev != NULL) + p->l_prev->l_next = p->l_next; + else + lp->l_next = p->l_next; + + if (p->l_next != NULL) + p->l_next->l_prev = p->l_prev; + else + lp->l_prev = p->l_prev; +} + +/* Convert a 32-bit ELF symbol into Elf64 and return a pointer to it. */ + +Elf64_Sym * +ctf_sym_to_elf64 (const Elf32_Sym *src, Elf64_Sym *dst) +{ + dst->st_name = src->st_name; + dst->st_value = src->st_value; + dst->st_size = src->st_size; + dst->st_info = src->st_info; + dst->st_other = src->st_other; + dst->st_shndx = src->st_shndx; + + return dst; +} + +/* Convert an encoded CTF string name into a pointer to a C string by looking + up the appropriate string table buffer and then adding the offset. */ + +const char * +ctf_strraw (ctf_file_t *fp, uint32_t name) +{ + ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID (name)]; + + if (ctsp->cts_strs != NULL && CTF_NAME_OFFSET (name) < ctsp->cts_len) + return (ctsp->cts_strs + CTF_NAME_OFFSET (name)); + + /* String table not loaded or corrupt offset. */ + return NULL; +} + +const char * +ctf_strptr (ctf_file_t *fp, uint32_t name) +{ + const char *s = ctf_strraw (fp, name); + return (s != NULL ? s : "(?)"); +} + +/* Same as strdup(3C), but use ctf_alloc() to do the memory allocation. */ + +_libctf_malloc_ char * +ctf_strdup (const char *s1) +{ + char *s2 = ctf_alloc (strlen (s1) + 1); + + if (s2 != NULL) + (void) strcpy (s2, s1); + + return s2; +} + +/* A string appender working on dynamic strings. */ + +char * +ctf_str_append (char *s, const char *append) +{ + size_t s_len = 0; + + if (append == NULL) + return s; + + if (s != NULL) + s_len = strlen (s); + + size_t append_len = strlen (append); + + if ((s = realloc (s, s_len + append_len + 1)) == NULL) + return NULL; + + memcpy (s + s_len, append, append_len); + s[s_len + append_len] = '\0'; + + return s; +} + +/* Store the specified error code into errp if it is non-NULL, and then + return NULL for the benefit of the caller. */ + +void * +ctf_set_open_errno (int *errp, int error) +{ + if (errp != NULL) + *errp = error; + return NULL; +} + +/* Store the specified error code into the CTF container, and then return + CTF_ERR for the benefit of the caller. */ + +long +ctf_set_errno (ctf_file_t * fp, int err) +{ + fp->ctf_errno = err; + return CTF_ERR; +} diff --git a/libctf/elf.h b/libctf/elf.h new file mode 100644 index 0000000000..fee1630909 --- /dev/null +++ b/libctf/elf.h @@ -0,0 +1,61 @@ +/* This file defines standard ELF types, structures, and macros. + Copyright (C) 1995-2019 Free Software Foundation, Inc. + + This file is part of libctf. + + libctf is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not see + . */ + +#ifndef _CTF_ELF_H +#define _CTF_ELF_H + +#include "config.h" +#include "ansidecl.h" +#include +#include "elf/common.h" +#include "elf/external.h" + +typedef uint32_t Elf32_Word; +typedef uint32_t Elf64_Word; +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Xword; +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +#define SHN_EXTABS 0xFFF1 /* Associated symbol is absolute */ + +/* Symbol table entry. */ + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +#endif /* _CTF_ELF_H */