utils.h 6.05 KB
Newer Older
1
2
3
4
5
6
// Copyright © 2017 Collabora Ltd

// This file is part of libcapsule.

// libcapsule is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
Simon McVittie's avatar
Simon McVittie committed
7
// published by the Free Software Foundation; either version 2.1 of the
8
9
10
11
12
13
14
15
16
17
18
19
// License, or (at your option) any later version.

// libcapsule 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 Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with libcapsule.  If not, see <http://www.gnu.org/licenses/>.

#pragma once

20
#include <limits.h>
21
#include <stdarg.h>
22
23
24
#include <stddef.h>
#include <stdlib.h>

25
#include <link.h> // for __ELF_NATIVE_CLASS
26

27
#include "debug.h"
28

29
30
31
#define UNLIKELY(x) __builtin_expect(x, 0)
#define LIKELY(x)   __builtin_expect(x, 1)

32
33
34
35
36
// these macros are secretly the same for elf32 & elf64:
#define ELFW_ST_TYPE(a)       ELF32_ST_TYPE(a)
#define ELFW_ST_BIND(a)       ELF32_ST_BIND(a)
#define ELFW_ST_VISIBILITY(a) ELF32_ST_VISIBILITY(a)

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#if __ELF_NATIVE_CLASS == 64
#define FMT_OFF   "lu"
#define FMT_SWORD "lu"
#define FMT_WORD  "ld"
#define FMT_SIZE  "lu"
#define FMT_ADDR  "ld"
#define FMT_XADDR "lx"
#define FMT_XU64  "lx"
#else
#define FMT_OFF   "u"
#define FMT_SWORD "u"
#define FMT_WORD  "d"
#define FMT_SIZE  "u"
#define FMT_ADDR  "d"
#define FMT_XADDR "x"
#define FMT_XU64  "llx"
#endif

55
56
57
58
59
60
61
62
63
64
65
66
67
typedef union ptr_item
{
    ElfW(Addr) addr;
    void *ptr;
} ptr_item;

typedef struct ptr_list
{
    size_t allocated;
    size_t next;
    ptr_item *loc;
} ptr_list;

68
69
typedef int (*ptrcmp) (const void *a, const void *b);

70
ptr_list *ptr_list_alloc (size_t size);
71
void *ptr_list_nth_ptr (ptr_list *list, size_t nth);
72
void ptr_list_free (ptr_list *list);
73
74
75
76
void ptr_list_push_ptr  (ptr_list *list, void *ptr);
void ptr_list_push_addr (ptr_list *list, ElfW(Addr) addr);
int  ptr_list_contains  (ptr_list *list, ElfW(Addr) addr);
int  ptr_list_add_ptr   (ptr_list *list, void *ptr, ptrcmp equals);
77

78
char *safe_strncpy (char *dest, const char *src, size_t n);
79
int   resolve_link (const char *prefix, char path[PATH_MAX]);
80
int soname_matches_path (const char *soname, const char *path);
81
82
83
size_t build_filename_va (char *buf, size_t len, const char *first_path, va_list ap);
size_t build_filename (char *buf, size_t len, const char *first_path, ...) __attribute__((sentinel));
char *build_filename_alloc (const char *first_path, ...) __attribute__((sentinel));
84

85
const void *      fix_addr (const void *base, ElfW(Addr) offset_or_addr);
86
const ElfW(Dyn) * find_dyn (ElfW(Addr) base, void *start, int what);
Simon McVittie's avatar
Simon McVittie committed
87
size_t            find_value (ElfW(Addr) base, void *start, int what);
88
ElfW(Addr)        find_ptr (ElfW(Addr) base, void *start, int what);
89
const char *      dynamic_section_find_strtab (const ElfW(Dyn) *entries, const void *base, size_t *siz);
90
91
const ElfW(Sym) * find_symbol (int idx,
                               const ElfW(Sym) *stab,
92
                               size_t symsz,
93
                               const char *str,
94
                               size_t strsz,
95
                               const char **name);
96
97
98
99
100

void oom( void ) __attribute__((noreturn));
char *xstrdup( const char *s );
void *xrealloc( void *ptr, size_t size ) __attribute__((alloc_size(2)));
void *xcalloc( size_t n, size_t size ) __attribute__((alloc_size(1, 2), malloc));
101
int xasprintf( char **s, const char *format, ...) __attribute__((format(printf, 2, 3)));
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

/*
 * _capsule_steal_pointer:
 * @pp: A non-%NULL pointer to any pointer type (void ** or Something **)
 *
 * Transfer the contents of @pp to the caller, setting @pp to %NULL.
 * This is essentially the same thing as g_steal_pointer().
 */
static inline void *
_capsule_steal_pointer( void *pp )
{
    typedef void *__attribute__((may_alias)) voidp_alias;
    voidp_alias *pointer_to_pointer = pp;
    void *ret = *pointer_to_pointer;
    *pointer_to_pointer = NULL;
    return ret;
}

/*
 * _capsule_propagate_error:
 * @code_dest: (out) (optional): where to put the error code (errno), or %NULL
 * @message_dest: (out) (transfer full) (optional) (nullable): where to
 *  put the message, or %NULL
 * @code_src: the error code (errno)
 * @message_src: (nullable) (transfer full): the error message
 *
 * This is essentially the same thing as g_propagate_error(), and leaves
 * message_src undefined. It should typically be used as:
 *
 *     _capsule_propagate_error( &code, &message, local_code,
 *                               _capsule_steal_pointer( &local_message ) );
 */
static inline void
_capsule_propagate_error( int *code_dest, char **message_dest, int code_src, char *message_src )
{
    if( code_dest != NULL )
        *code_dest = code_src;

    if( message_dest != NULL )
        *message_dest = message_src;
    else
        free( message_src );
}

void _capsule_set_error_literal( int *code_dest, char **message_dest,
                                 int code, const char *message );

void _capsule_set_error( int *code_dest, char **message_dest,
                         int code, const char *format, ... )
    __attribute__((format(printf, 4, 5)));
152
153
154
155
156
157
158
159

/*
 * N_ELEMENTS:
 * @array: A fixed-size array (not a pointer!)
 *
 * Same as `G_N_ELEMENTS`, `_DBUS_N_ELEMENTS`, systemd `ELEMENTSOF`, etc.
 */
#define N_ELEMENTS(array) ( sizeof(array) / sizeof(array[0]) )
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

/*
 * _capsule_clear:
 * @pp: A pointer to a pointer that can be freed by Standard C `free()`,
 *  i.e. type `void **`, `char **` or more rarely `something **`
 *
 * Free whatever object is pointed to by `*pp`, and set `*pp` to NULL.
 */
static inline void
_capsule_clear( void *pp )
{
    free( _capsule_steal_pointer( pp ) );
}

/*
 * _capsule_cleanup:
 * @clear:
 *
 * An attribute marking a variable to be cleared by `clear(&variable)`
 * on exit from its scope.
 */
#define _capsule_cleanup(clear) __attribute__((cleanup(clear)))

/*
 * _capsule_autofree:
 *
 * An attribute marking a variable to be freed by `free(variable)`
 * on exit from its scope.
 */
#define _capsule_autofree _capsule_cleanup(_capsule_clear)