Print this page
Append to the string and symbol tables by allocating a new data
descriptor, rather than copying and extending the buffers returned by
libelf.


   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