7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #define ELF_TARGET_ALL
30 #include <elf.h>
31
32 #include <sys/types.h>
33 #include <sys/sysmacros.h>
34
35 #include <unistd.h>
36 #include <strings.h>
37 #include <alloca.h>
38 #include <limits.h>
39 #include <stddef.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <errno.h>
44 #include <wait.h>
45 #include <assert.h>
46 #include <sys/ipc.h>
47
1013 static const char dt_enabled[] = "enabled";
1014 static const char dt_symprefix[] = "$dtrace";
1015 static const char dt_symfmt[] = "%s%d.%s";
1016 int fd, i, ndx, eprobe, mod = 0;
1017 Elf *elf = NULL;
1018 GElf_Ehdr ehdr;
1019 Elf_Scn *scn_rel, *scn_sym, *scn_str, *scn_tgt;
1020 Elf_Data *data_rel, *data_sym, *data_str, *data_tgt;
1021 GElf_Shdr shdr_rel, shdr_sym, shdr_str, shdr_tgt;
1022 GElf_Sym rsym, fsym, dsym;
1023 GElf_Rela rela;
1024 char *s, *p, *r;
1025 char pname[DTRACE_PROVNAMELEN];
1026 dt_provider_t *pvp;
1027 dt_probe_t *prp;
1028 uint32_t off, eclass, emachine1, emachine2;
1029 size_t symsize, nsym, isym, istr, len;
1030 key_t objkey;
1031 dt_link_pair_t *pair, *bufs = NULL;
1032 dt_strtab_t *strtab;
1033
1034 if ((fd = open64(obj, O_RDWR)) == -1) {
1035 return (dt_link_error(dtp, elf, fd, bufs,
1036 "failed to open %s: %s", obj, strerror(errno)));
1037 }
1038
1039 if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
1040 return (dt_link_error(dtp, elf, fd, bufs,
1041 "failed to process %s: %s", obj, elf_errmsg(elf_errno())));
1042 }
1043
1044 switch (elf_kind(elf)) {
1045 case ELF_K_ELF:
1046 break;
1047 case ELF_K_AR:
1048 return (dt_link_error(dtp, elf, fd, bufs, "archives are not "
1049 "permitted; use the contents of the archive instead: %s",
1050 obj));
1051 default:
1052 return (dt_link_error(dtp, elf, fd, bufs,
1245 * buffers, and marking the buffers as dirty. We inject those
1246 * newly allocated buffers into the libelf data structures, but
1247 * are still responsible for freeing them once we're done with
1248 * the elf handle.
1249 */
1250 if (nsym > 0) {
1251 /*
1252 * The first byte of the string table is reserved for
1253 * the \0 entry.
1254 */
1255 len = dt_strtab_size(strtab) - 1;
1256
1257 assert(len > 0);
1258 assert(dt_strtab_index(strtab, "") == 0);
1259
1260 dt_strtab_destroy(strtab);
1261
1262 if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL)
1263 goto err;
1264
1265 if ((pair->dlp_str = dt_alloc(dtp, data_str->d_size +
1266 len)) == NULL) {
1267 dt_free(dtp, pair);
1268 goto err;
1269 }
1270
1271 if ((pair->dlp_sym = dt_alloc(dtp, data_sym->d_size +
1272 nsym * symsize)) == NULL) {
1273 dt_free(dtp, pair->dlp_str);
1274 dt_free(dtp, pair);
1275 goto err;
1276 }
1277
1278 pair->dlp_next = bufs;
1279 bufs = pair;
1280
1281 bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size);
1282 data_str->d_buf = pair->dlp_str;
1283 data_str->d_size += len;
1284 (void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
1285
1286 shdr_str.sh_size += len;
1287 (void) gelf_update_shdr(scn_str, &shdr_str);
1288
1289 bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size);
1290 data_sym->d_buf = pair->dlp_sym;
1291 data_sym->d_size += nsym * symsize;
1292 (void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
1293
1294 shdr_sym.sh_size += nsym * symsize;
1295 (void) gelf_update_shdr(scn_sym, &shdr_sym);
1296
1297 nsym += isym;
1298 } else {
1299 dt_strtab_destroy(strtab);
1300 }
1301
1302 /*
1303 * Now that the tables have been allocated, perform the
1304 * modifications described above.
1305 */
1306 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1307
1308 if (shdr_rel.sh_type == SHT_RELA) {
1309 if (gelf_getrela(data_rel, i, &rela) == NULL)
1310 continue;
1311 } else {
1312 GElf_Rel rel;
1313 if (gelf_getrel(data_rel, i, &rel) == NULL)
1314 continue;
1315 rela.r_offset = rel.r_offset;
1340 eprobe = 1;
1341 *eprobesp = 1;
1342 dt_dprintf("is-enabled probe\n");
1343 } else {
1344 eprobe = 0;
1345 dt_dprintf("normal probe\n");
1346 }
1347
1348 if (*s++ != '_')
1349 goto err;
1350
1351 if ((p = strstr(s, "___")) == NULL ||
1352 p - s >= sizeof (pname))
1353 goto err;
1354
1355 bcopy(s, pname, p - s);
1356 pname[p - s] = '\0';
1357
1358 p = strhyphenate(p + 3); /* strlen("___") */
1359
1360 if (dt_symtab_lookup(data_sym, isym, rela.r_offset,
1361 shdr_rel.sh_info, &fsym) != 0)
1362 goto err;
1363
1364 if (fsym.st_name > data_str->d_size)
1365 goto err;
1366
1367 assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC);
1368
1369 /*
1370 * If a NULL relocation name is passed to
1371 * dt_probe_define(), the function name is used for the
1372 * relocation. The relocation needs to use a mangled
1373 * name if the symbol is locally scoped; the function
1374 * name may need to change if we've found the global
1375 * alias for the locally scoped symbol (we prefer
1376 * global symbols to locals in dt_symtab_lookup()).
1377 */
1378 s = (char *)data_str->d_buf + fsym.st_name;
1379 r = NULL;
1380
1381 if (GELF_ST_BIND(fsym.st_info) == STB_LOCAL) {
1382 dsym = fsym;
1383 dsym.st_name = istr;
1384 dsym.st_info = GELF_ST_INFO(STB_GLOBAL,
1385 STT_FUNC);
1386 dsym.st_other =
1387 ELF64_ST_VISIBILITY(STV_ELIMINATE);
1388 (void) gelf_update_sym(data_sym, isym, &dsym);
1389
1390 r = (char *)data_str->d_buf + istr;
1391 istr += 1 + sprintf(r, dt_symfmt,
1392 dt_symprefix, objkey, s);
1393 isym++;
1394 assert(isym <= nsym);
1395
1396 } else if (strncmp(s, dt_symprefix,
1397 strlen(dt_symprefix)) == 0) {
1398 r = s;
1399 if ((s = strchr(s, '.')) == NULL)
1400 goto err;
1401 s++;
1402 }
1403
1404 if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) {
1405 return (dt_link_error(dtp, elf, fd, bufs,
1406 "no such provider %s", pname));
1407 }
1408
1409 if ((prp = dt_probe_lookup(pvp, p)) == NULL) {
1410 return (dt_link_error(dtp, elf, fd, bufs,
1411 "no such probe %s", p));
1412 }
1413
|
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright (c) 2013 by Delphix. All rights reserved.
29 */
30
31 #define ELF_TARGET_ALL
32 #include <elf.h>
33
34 #include <sys/types.h>
35 #include <sys/sysmacros.h>
36
37 #include <unistd.h>
38 #include <strings.h>
39 #include <alloca.h>
40 #include <limits.h>
41 #include <stddef.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <fcntl.h>
45 #include <errno.h>
46 #include <wait.h>
47 #include <assert.h>
48 #include <sys/ipc.h>
49
1015 static const char dt_enabled[] = "enabled";
1016 static const char dt_symprefix[] = "$dtrace";
1017 static const char dt_symfmt[] = "%s%d.%s";
1018 int fd, i, ndx, eprobe, mod = 0;
1019 Elf *elf = NULL;
1020 GElf_Ehdr ehdr;
1021 Elf_Scn *scn_rel, *scn_sym, *scn_str, *scn_tgt;
1022 Elf_Data *data_rel, *data_sym, *data_str, *data_tgt;
1023 GElf_Shdr shdr_rel, shdr_sym, shdr_str, shdr_tgt;
1024 GElf_Sym rsym, fsym, dsym;
1025 GElf_Rela rela;
1026 char *s, *p, *r;
1027 char pname[DTRACE_PROVNAMELEN];
1028 dt_provider_t *pvp;
1029 dt_probe_t *prp;
1030 uint32_t off, eclass, emachine1, emachine2;
1031 size_t symsize, nsym, isym, istr, len;
1032 key_t objkey;
1033 dt_link_pair_t *pair, *bufs = NULL;
1034 dt_strtab_t *strtab;
1035 Elf_Data *data_newsym, *data_newstr;
1036 size_t newsym = 0;
1037
1038 if ((fd = open64(obj, O_RDWR)) == -1) {
1039 return (dt_link_error(dtp, elf, fd, bufs,
1040 "failed to open %s: %s", obj, strerror(errno)));
1041 }
1042
1043 if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
1044 return (dt_link_error(dtp, elf, fd, bufs,
1045 "failed to process %s: %s", obj, elf_errmsg(elf_errno())));
1046 }
1047
1048 switch (elf_kind(elf)) {
1049 case ELF_K_ELF:
1050 break;
1051 case ELF_K_AR:
1052 return (dt_link_error(dtp, elf, fd, bufs, "archives are not "
1053 "permitted; use the contents of the archive instead: %s",
1054 obj));
1055 default:
1056 return (dt_link_error(dtp, elf, fd, bufs,
1249 * buffers, and marking the buffers as dirty. We inject those
1250 * newly allocated buffers into the libelf data structures, but
1251 * are still responsible for freeing them once we're done with
1252 * the elf handle.
1253 */
1254 if (nsym > 0) {
1255 /*
1256 * The first byte of the string table is reserved for
1257 * the \0 entry.
1258 */
1259 len = dt_strtab_size(strtab) - 1;
1260
1261 assert(len > 0);
1262 assert(dt_strtab_index(strtab, "") == 0);
1263
1264 dt_strtab_destroy(strtab);
1265
1266 if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL)
1267 goto err;
1268
1269 if ((pair->dlp_str = dt_alloc(dtp, len)) == NULL) {
1270 dt_free(dtp, pair);
1271 goto err;
1272 }
1273
1274 if ((pair->dlp_sym =
1275 dt_alloc(dtp, nsym * symsize)) == NULL) {
1276 dt_free(dtp, pair->dlp_str);
1277 dt_free(dtp, pair);
1278 goto err;
1279 }
1280
1281 pair->dlp_next = bufs;
1282 bufs = pair;
1283
1284 if ((data_newstr = elf_newdata(scn_str)) == NULL)
1285 goto err;
1286 data_newstr->d_size = len;
1287 data_newstr->d_buf = pair->dlp_str;
1288
1289 if ((data_newsym = elf_newdata(scn_sym)) == NULL)
1290 goto err;
1291 data_newsym->d_size = nsym * symsize;
1292 data_newsym->d_buf = pair->dlp_sym;
1293
1294 nsym += isym;
1295 } else {
1296 dt_strtab_destroy(strtab);
1297 }
1298
1299 /*
1300 * Now that the tables have been allocated, perform the
1301 * modifications described above.
1302 */
1303 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1304
1305 if (shdr_rel.sh_type == SHT_RELA) {
1306 if (gelf_getrela(data_rel, i, &rela) == NULL)
1307 continue;
1308 } else {
1309 GElf_Rel rel;
1310 if (gelf_getrel(data_rel, i, &rel) == NULL)
1311 continue;
1312 rela.r_offset = rel.r_offset;
1337 eprobe = 1;
1338 *eprobesp = 1;
1339 dt_dprintf("is-enabled probe\n");
1340 } else {
1341 eprobe = 0;
1342 dt_dprintf("normal probe\n");
1343 }
1344
1345 if (*s++ != '_')
1346 goto err;
1347
1348 if ((p = strstr(s, "___")) == NULL ||
1349 p - s >= sizeof (pname))
1350 goto err;
1351
1352 bcopy(s, pname, p - s);
1353 pname[p - s] = '\0';
1354
1355 p = strhyphenate(p + 3); /* strlen("___") */
1356
1357 if (dt_symtab_lookup(data_newsym, newsym,
1358 rela.r_offset, shdr_rel.sh_info, &fsym) == 0) {
1359 if (fsym.st_name >= data_str->d_size +
1360 data_newstr->d_size)
1361 goto err;
1362 s = (char *)data_newstr->d_buf +
1363 fsym.st_name - data_str->d_size;
1364 } else if (dt_symtab_lookup(data_sym, isym,
1365 rela.r_offset, shdr_rel.sh_info, &fsym) == 0) {
1366 if (fsym.st_name >= data_str->d_size)
1367 goto err;
1368 s = (char *)data_str->d_buf + fsym.st_name;
1369 } else {
1370 goto err;
1371 }
1372
1373 assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC);
1374
1375 /*
1376 * If a NULL relocation name is passed to
1377 * dt_probe_define(), the function name is used for the
1378 * relocation. The relocation needs to use a mangled
1379 * name if the symbol is locally scoped; the function
1380 * name may need to change if we've found the global
1381 * alias for the locally scoped symbol (we prefer
1382 * global symbols to locals in dt_symtab_lookup()).
1383 */
1384 r = NULL;
1385
1386 if (GELF_ST_BIND(fsym.st_info) == STB_LOCAL) {
1387 dsym = fsym;
1388 dsym.st_name = istr;
1389 dsym.st_info = GELF_ST_INFO(STB_GLOBAL,
1390 STT_FUNC);
1391 dsym.st_other =
1392 ELF64_ST_VISIBILITY(STV_ELIMINATE);
1393 (void)gelf_update_sym(data_newsym, newsym,
1394 &dsym);
1395
1396 r = (char *)data_newstr->d_buf +
1397 (istr - data_str->d_size);
1398 istr += 1 + sprintf(r, dt_symfmt,
1399 dt_symprefix, objkey, s);
1400 isym++;
1401 newsym++;
1402 assert(isym <= nsym);
1403
1404 } else if (strncmp(s, dt_symprefix,
1405 strlen(dt_symprefix)) == 0) {
1406 r = s;
1407 if ((s = strchr(s, '.')) == NULL)
1408 goto err;
1409 s++;
1410 }
1411
1412 if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) {
1413 return (dt_link_error(dtp, elf, fd, bufs,
1414 "no such provider %s", pname));
1415 }
1416
1417 if ((prp = dt_probe_lookup(pvp, p)) == NULL) {
1418 return (dt_link_error(dtp, elf, fd, bufs,
1419 "no such probe %s", p));
1420 }
1421
|