File: mkoffsets.sh

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (222 lines) | stat: -rwxr-xr-x 6,665 bytes parent folder | download
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
154
155
156
157
158
159
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#!/bin/bash
#
# Compute a variety of offsets needed for monitoring of ptrace()d processes'
# dynamic linker, and write them to the file name in $1. We assume that no
# CFLAGS are provided that change the ABI (because the ABI we rely upon is that
# of the child process, not that of dtrace).
#
#
# Oracle Linux DTrace.
# Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.

HEADER=$1
INIT=$2
NATIVE_BITNESS_ONLY=$3
NATIVE_BITNESS=

if [[ -n $NATIVE_BITNESS_ONLY ]]; then
    NATIVE_BITNESS=64
fi

NATIVE_BITNESS_OPTION_SUPPORTED="$(echo 'int main (void) { }' | ${CC:-gcc} -x c -o /dev/null -m64 - 2>/dev/null && echo t)"

set -e

# Header file.
cat >$HEADER <<EOF
/* Offsets and sizes for various structures in the dynamic linker.

   This is a generated file. */

EOF
echo '#ifndef _'$(basename $HEADER | tr '[a-z.]' '[A-Z_]')'_' >> $HEADER
echo '#define _'$(basename $HEADER | tr '[a-z.]' '[A-Z_]')'_' >> $HEADER
echo >>$HEADER

for BITNESS in 32 64; do
    BITNESS_ARG="-m${NATIVE_BITNESS:-$BITNESS}"
    if [[ "$BITNESS_ARG" = "-m$NATIVE_BITNESS" ]] &&
       [[ -z $NATIVE_BITNESS_OPTION_SUPPORTED ]]; then
	BITNESS_ARG=
    fi
    sed "s,@BITNESS@,$BITNESS,g" <<'EOF' | \
    $CC -std=gnu99 -o $objdir/mkoffsets $CPPFLAGS $BITNESS_ARG -DBITNESS=$BITNESS \
	${NATIVE_BITNESS:+-DNATIVE_BITNESS=$NATIVE_BITNESS} -DCOMPILE_TIME -D_GNU_SOURCE -x c - >/dev/null
/* Compute the offsets and sizes of various structure fields in the dynamic
   linker needed for debugging.

   This is a generated file. */

#include <stddef.h>
#include <stdio.h>
#include <sys/glibc_internal_link.h>

#if defined(NATIVE_BITNESS) && NATIVE_BITNESS != BITNESS
#define BITNESS_OFFSET(name, s, m) \
	printf("#define " #name "_@BITNESS@_OFFSET\t0\n"); \
	printf("#define " #name "_@BITNESS@_SIZE\t0\n")
#else
#define BITNESS_OFFSET(name, s, m) \
	printf("#define " #name "_@BITNESS@_OFFSET\t%li\n", \
		offsetof(struct s, m)); \
	printf("#define " #name "_@BITNESS@_SIZE\t%li\n", \
		sizeof(((struct s *)0)->m))
#endif

int main(void)
{
	printf("#define UINT_@BITNESS@_SIZE\t%li\n", sizeof(unsigned int));
	printf("#define PTR_@BITNESS@_SIZE\t%li\n", sizeof(void *));
	printf("#ifndef DL_NNS\n");
	printf("#define DL_NNS\t%li\n", DL_NNS);
	printf("#endif\n");

	printf("#define R_DEBUG_@BITNESS@_SIZE\t%li\n", sizeof (struct r_debug));
	printf("#define LINK_NAMESPACES_@BITNESS@_SIZE\t%li\n",
	       sizeof (struct link_namespaces));

	BITNESS_OFFSET(R_VERSION, r_debug, r_version);
	BITNESS_OFFSET(R_MAP, r_debug, r_map);
	BITNESS_OFFSET(R_BRK, r_debug, r_brk);
	BITNESS_OFFSET(R_STATE, r_debug, r_state);
	BITNESS_OFFSET(R_LDBASE, r_debug, r_ldbase);

	BITNESS_OFFSET(L_ADDR, internal_link_map, l_addr);
	BITNESS_OFFSET(L_NAME, internal_link_map, l_name);
	BITNESS_OFFSET(L_LD, internal_link_map, l_ld);
	BITNESS_OFFSET(L_NEXT, internal_link_map, l_next);
	BITNESS_OFFSET(L_PREV, internal_link_map, l_prev);
	BITNESS_OFFSET(L_SEARCHLIST, internal_link_map, l_searchlist.r_list);

	BITNESS_OFFSET(G_DEBUG, rtld_global, _dl_ns[0]._ns_debug);
	BITNESS_OFFSET(G_NLOADED, rtld_global, _dl_ns[0]._ns_nloaded);
	BITNESS_OFFSET(G_NS_LOADED, rtld_global, _dl_ns[0]._ns_loaded);
	BITNESS_OFFSET(G_DL_NNS, rtld_global, _dl_nns);
	BITNESS_OFFSET(G_DL_LOAD_LOCK, rtld_global, _dl_load_lock.mutex.__data.__count);
}
EOF

    ERR=${PIPESTATUS[0]}
    [[ $ERR -ne 0 ]] && exit $ERR

    $objdir/mkoffsets >> $HEADER
    rm -f $objdir/mkoffsets
    echo >> $HEADER
done

cat >> $HEADER <<'EOF'
#if R_LDBASE_32_OFFSET > R_LDBASE_64_OFFSET
#define R_LAST_OFFSET R_LDBASE_32_OFFSET
#else
#define R_LAST_OFFSET R_LDBASE_64_OFFSET
#endif

#if L_SEARCHLIST_32_OFFSET > L_SEARCHLIST_64_OFFSET
#define L_LAST_OFFSET L_SEARCHLIST_32_OFFSET
#else
#define L_LAST_OFFSET L_SEARCHLIST_64_OFFSET
#endif

/*
 * Index field sizes by native offset.  (Only possible for those structures
 * with a public definition outside glibc_internal_link.h.  Other structure
 * offset computations must be done the ugly way.)
 *
 * This won't cope with unions, but will do for now, and frees us from
 * having to litter the code with ugly R_ and L_ constants.
 */

typedef struct rtld_offsets {
	size_t offset[2];
	size_t size[2];
} rtld_offsets_t;

extern rtld_offsets_t r_debug_offsets[R_LAST_OFFSET+1];
extern rtld_offsets_t link_map_offsets[L_LAST_OFFSET+1];

#endif
EOF

# .c file (initialization).

build_offsets_all()
{
    # Note: this will fail if 32-bit compilation of DTrace is attempted,
    # since it assumes that the native offsets are the 64-bit ones.
    # This is almost certainly not worth fixing.
    for name in $(grep '^#define' $HEADER | grep -v 'LAST_OFFSET' | \
		  grep -o " ${2}"'_.*_64_OFFSET'); do
	name_32_offset="$(echo $name | sed 's,_64,_32,')"
	name_64_size="$(echo $name | sed 's,_OFFSET,_SIZE,')"
	name_32_size="$(echo $name | sed 's,_64_OFFSET,_32_SIZE,')"
    cat >> $INIT <<EOF
	rtld_offsets_t ${name}_build = {{${name_32_offset}, ${name}}, {${name_32_size},${name_64_size}}};
	$1_build[${name}] = ${name}_build;
EOF
    done
}

build_offsets_native_only()
{
    for name in $(grep '^#define' $HEADER | grep -v 'LAST_OFFSET' | \
		  grep -o " ${2}"'_.*_64_OFFSET'); do
	name_64_size="$(echo $name | sed 's,_OFFSET,_SIZE,')"
    cat >> $INIT <<EOF
	rtld_offsets_t ${name}_build = {{0, ${name}}, {0, ${name_64_size}}};
	$1_build[${name}] = ${name}_build;
EOF
    done
}

if [[ -z $NATIVE_BITNESS_ONLY ]]; then
    build_offsets=build_offsets_all
else
    build_offsets=build_offsets_native_only
fi

cat > $INIT <<'EOF'
/* Initialize offsets and sizes for various structures in the dynamic linker.

   This is a generated file. */

#include <sys/compiler.h>
#include <string.h>
#include "rtld_offsets.h"

rtld_offsets_t r_debug_offsets[R_LAST_OFFSET+1];
rtld_offsets_t link_map_offsets[L_LAST_OFFSET+1];
static int initialized;

_dt_constructor_(rtld_offsets_init)
static void rtld_offsets_init(void)
{
	if (initialized)
		return;

	rtld_offsets_t r_debug_offsets_build[R_LAST_OFFSET+1];
	rtld_offsets_t link_map_offsets_build[L_LAST_OFFSET+1];

	memset(r_debug_offsets_build, 0, sizeof(struct rtld_offsets) *
	    (R_LAST_OFFSET+1));

EOF
$build_offsets r_debug_offsets R

cat >> $INIT <<'EOF'
	memcpy((void *)r_debug_offsets, r_debug_offsets_build,
	    sizeof(r_debug_offsets_build));

	memset((void *)link_map_offsets_build, 0, sizeof(struct rtld_offsets) *
	    (L_LAST_OFFSET+1));

EOF
$build_offsets link_map_offsets L
cat >> $INIT <<'EOF'

	memcpy((void *)link_map_offsets, link_map_offsets_build,
	    sizeof(link_map_offsets_build));
	initialized = 1;
}
EOF