Remove non-FreeBSD ifdefs from dt_link.c.

This file is too complicated as it is and has diverged a fair bit from
illumos due to toolchain differences, so just drop unused code
(including SPARC support).

MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Mark Johnston 2020-08-20 19:27:49 +00:00
parent 9f58ad6a45
commit 0e15d9fbeb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=364437

View File

@ -25,38 +25,23 @@
* Copyright 2017-2018 Mark Johnston <markj@FreeBSD.org>
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/wait.h>
#define ELF_TARGET_ALL
#include <assert.h>
#include <elf.h>
#include <sys/types.h>
#ifdef illumos
#include <sys/sysmacros.h>
#else
#define P2ROUNDUP(x, align) (-(-(x) & -(align)))
#endif
#include <unistd.h>
#include <strings.h>
#ifdef illumos
#include <alloca.h>
#endif
#include <fcntl.h>
#include <gelf.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
#ifdef illumos
#include <wait.h>
#else
#include <sys/wait.h>
#include <unistd.h>
#include <libelf.h>
#include <gelf.h>
#include <sys/mman.h>
#endif
#include <assert.h>
#include <dt_impl.h>
#include <dt_provider.h>
@ -82,11 +67,7 @@ static const char DTRACE_SHSTRTAB32[] = "\0"
".SUNW_dof\0" /* 11 */
".strtab\0" /* 21 */
".symtab\0" /* 29 */
#ifdef __sparc
".rela.SUNW_dof"; /* 37 */
#else
".rel.SUNW_dof"; /* 37 */
#endif
static const char DTRACE_SHSTRTAB64[] = "\0"
".shstrtab\0" /* 1 */
@ -106,11 +87,7 @@ typedef struct dt_link_pair {
typedef struct dof_elf32 {
uint32_t de_nrel; /* relocation count */
#ifdef __sparc
Elf32_Rela *de_rel; /* array of relocations for sparc */
#else
Elf32_Rel *de_rel; /* array of relocations for x86 */
#endif
uint32_t de_nsym; /* symbol count */
Elf32_Sym *de_sym; /* array of symbols */
uint32_t de_strlen; /* size of of string table */
@ -130,11 +107,7 @@ prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep)
uint32_t count = 0;
size_t base;
Elf32_Sym *sym;
#ifdef __sparc
Elf32_Rela *rel;
#else
Elf32_Rel *rel;
#endif
/*LINTED*/
dofs = (dof_sec_t *)((char *)dof + dof->dofh_secoff);
@ -324,11 +297,7 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep)
char *strtab;
int i, j, nrel;
size_t strtabsz = 1;
#ifdef illumos
uint32_t count = 0;
#else
uint64_t count = 0;
#endif
size_t base;
Elf64_Sym *sym;
Elf64_Rela *rel;
@ -530,9 +499,7 @@ dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
#else
elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
#endif
#if defined(__FreeBSD__)
elf_file.ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
#endif
elf_file.ehdr.e_type = ET_REL;
#if defined(__arm__)
elf_file.ehdr.e_machine = EM_ARM;
@ -540,8 +507,6 @@ dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
elf_file.ehdr.e_machine = EM_MIPS;
#elif defined(__powerpc__)
elf_file.ehdr.e_machine = EM_PPC;
#elif defined(__sparc)
elf_file.ehdr.e_machine = EM_SPARC;
#elif defined(__i386) || defined(__amd64)
elf_file.ehdr.e_machine = EM_386;
#elif defined(__aarch64__)
@ -562,7 +527,7 @@ dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
shp->sh_offset = off;
shp->sh_size = sizeof (DTRACE_SHSTRTAB32);
shp->sh_addralign = sizeof (char);
off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8);
off = roundup2(shp->sh_offset + shp->sh_size, 8);
shp = &elf_file.shdr[ESHDR_DOF];
shp->sh_name = 11; /* DTRACE_SHSTRTAB32[11] = ".SUNW_dof" */
@ -580,7 +545,7 @@ dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
shp->sh_offset = off;
shp->sh_size = de.de_strlen;
shp->sh_addralign = sizeof (char);
off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 4);
off = roundup2(shp->sh_offset + shp->sh_size, 4);
shp = &elf_file.shdr[ESHDR_SYMTAB];
shp->sh_name = 29; /* DTRACE_SHSTRTAB32[29] = ".symtab" */
@ -592,7 +557,7 @@ dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
shp->sh_info = de.de_global;
shp->sh_size = de.de_nsym * sizeof (Elf32_Sym);
shp->sh_addralign = 4;
off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 4);
off = roundup2(shp->sh_offset + shp->sh_size, 4);
if (de.de_nrel == 0) {
if (dt_write(dtp, fd, &elf_file,
@ -607,11 +572,7 @@ dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
shp = &elf_file.shdr[ESHDR_REL];
shp->sh_name = 37; /* DTRACE_SHSTRTAB32[37] = ".rel.SUNW_dof" */
shp->sh_flags = SHF_ALLOC;
#ifdef __sparc
shp->sh_type = SHT_RELA;
#else
shp->sh_type = SHT_REL;
#endif
shp->sh_entsize = sizeof (de.de_rel[0]);
shp->sh_link = ESHDR_SYMTAB;
shp->sh_info = ESHDR_DOF;
@ -678,9 +639,7 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
#else
elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
#endif
#if defined(__FreeBSD__)
elf_file.ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
#endif
elf_file.ehdr.e_type = ET_REL;
#if defined(__arm__)
elf_file.ehdr.e_machine = EM_ARM;
@ -691,8 +650,6 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
elf_file.ehdr.e_flags = 2;
#endif
elf_file.ehdr.e_machine = EM_PPC64;
#elif defined(__sparc)
elf_file.ehdr.e_machine = EM_SPARCV9;
#elif defined(__i386) || defined(__amd64)
elf_file.ehdr.e_machine = EM_AMD64;
#elif defined(__aarch64__)
@ -713,7 +670,7 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
shp->sh_offset = off;
shp->sh_size = sizeof (DTRACE_SHSTRTAB64);
shp->sh_addralign = sizeof (char);
off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8);
off = roundup2(shp->sh_offset + shp->sh_size, 8);
shp = &elf_file.shdr[ESHDR_DOF];
shp->sh_name = 11; /* DTRACE_SHSTRTAB64[11] = ".SUNW_dof" */
@ -731,7 +688,7 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
shp->sh_offset = off;
shp->sh_size = de.de_strlen;
shp->sh_addralign = sizeof (char);
off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8);
off = roundup2(shp->sh_offset + shp->sh_size, 8);
shp = &elf_file.shdr[ESHDR_SYMTAB];
shp->sh_name = 29; /* DTRACE_SHSTRTAB64[29] = ".symtab" */
@ -743,7 +700,7 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
shp->sh_info = de.de_global;
shp->sh_size = de.de_nsym * sizeof (Elf64_Sym);
shp->sh_addralign = 8;
off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8);
off = roundup2(shp->sh_offset + shp->sh_size, 8);
if (de.de_nrel == 0) {
if (dt_write(dtp, fd, &elf_file,
@ -984,132 +941,6 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
__FILE__, __LINE__);
return (-1);
}
#elif defined(__sparc)
#define DT_OP_RET 0x81c7e008
#define DT_OP_NOP 0x01000000
#define DT_OP_CALL 0x40000000
#define DT_OP_CLR_O0 0x90102000
#define DT_IS_MOV_O7(inst) (((inst) & 0xffffe000) == 0x9e100000)
#define DT_IS_RESTORE(inst) (((inst) & 0xc1f80000) == 0x81e80000)
#define DT_IS_RETL(inst) (((inst) & 0xfff83fff) == 0x81c02008)
#define DT_RS2(inst) ((inst) & 0x1f)
#define DT_MAKE_RETL(reg) (0x81c02008 | ((reg) << 14))
/*ARGSUSED*/
static int
dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
uint32_t *off)
{
uint32_t *ip;
if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
return (-1);
/*LINTED*/
ip = (uint32_t *)(p + rela->r_offset);
/*
* We only know about some specific relocation types.
*/
if (GELF_R_TYPE(rela->r_info) != R_SPARC_WDISP30 &&
GELF_R_TYPE(rela->r_info) != R_SPARC_WPLT30)
return (-1);
/*
* We may have already processed this object file in an earlier linker
* invocation. Check to see if the present instruction sequence matches
* the one we would install below.
*/
if (isenabled) {
if (ip[0] == DT_OP_NOP) {
(*off) += sizeof (ip[0]);
return (0);
}
} else {
if (DT_IS_RESTORE(ip[1])) {
if (ip[0] == DT_OP_RET) {
(*off) += sizeof (ip[0]);
return (0);
}
} else if (DT_IS_MOV_O7(ip[1])) {
if (DT_IS_RETL(ip[0]))
return (0);
} else {
if (ip[0] == DT_OP_NOP) {
(*off) += sizeof (ip[0]);
return (0);
}
}
}
/*
* We only expect call instructions with a displacement of 0.
*/
if (ip[0] != DT_OP_CALL) {
dt_dprintf("found %x instead of a call instruction at %llx\n",
ip[0], (u_longlong_t)rela->r_offset);
return (-1);
}
if (isenabled) {
/*
* It would necessarily indicate incorrect usage if an is-
* enabled probe were tail-called so flag that as an error.
* It's also potentially (very) tricky to handle gracefully,
* but could be done if this were a desired use scenario.
*/
if (DT_IS_RESTORE(ip[1]) || DT_IS_MOV_O7(ip[1])) {
dt_dprintf("tail call to is-enabled probe at %llx\n",
(u_longlong_t)rela->r_offset);
return (-1);
}
/*
* On SPARC, we take advantage of the fact that the first
* argument shares the same register as for the return value.
* The macro handles the work of zeroing that register so we
* don't need to do anything special here. We instrument the
* instruction in the delay slot as we'll need to modify the
* return register after that instruction has been emulated.
*/
ip[0] = DT_OP_NOP;
(*off) += sizeof (ip[0]);
} else {
/*
* If the call is followed by a restore, it's a tail call so
* change the call to a ret. If the call if followed by a mov
* of a register into %o7, it's a tail call in leaf context
* so change the call to a retl-like instruction that returns
* to that register value + 8 (rather than the typical %o7 +
* 8); the delay slot instruction is left, but should have no
* effect. Otherwise we change the call to be a nop. We
* identify the subsequent instruction as the probe point in
* all but the leaf tail-call case to ensure that arguments to
* the probe are complete and consistent. An astute, though
* largely hypothetical, observer would note that there is the
* possibility of a false-positive probe firing if the function
* contained a branch to the instruction in the delay slot of
* the call. Fixing this would require significant in-kernel
* modifications, and isn't worth doing until we see it in the
* wild.
*/
if (DT_IS_RESTORE(ip[1])) {
ip[0] = DT_OP_RET;
(*off) += sizeof (ip[0]);
} else if (DT_IS_MOV_O7(ip[1])) {
ip[0] = DT_MAKE_RETL(DT_RS2(ip[1]));
} else {
ip[0] = DT_OP_NOP;
(*off) += sizeof (ip[0]);
}
}
return (0);
}
#elif defined(__i386) || defined(__amd64)
@ -1334,8 +1165,6 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
#if !defined(_CALL_ELF) || _CALL_ELF == 1
uses_funcdesc = 1;
#endif
#elif defined(__sparc)
emachine1 = emachine2 = EM_SPARCV9;
#elif defined(__i386) || defined(__amd64)
emachine1 = emachine2 = EM_AMD64;
#elif defined(__aarch64__)
@ -1350,9 +1179,6 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
emachine1 = emachine2 = EM_MIPS;
#elif defined(__powerpc__)
emachine1 = emachine2 = EM_PPC;
#elif defined(__sparc)
emachine1 = EM_SPARC;
emachine2 = EM_SPARC32PLUS;
#elif defined(__i386) || defined(__amd64)
emachine1 = emachine2 = EM_386;
#endif
@ -1716,7 +1542,7 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
return (dt_link_error(dtp, elf, fd, bufs,
"failed to allocate space for probe"));
}
#ifndef illumos
/*
* Our linker doesn't understand the SUNW_IGNORE ndx and
* will try to use this relocation when we build the
@ -1738,7 +1564,6 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
rel.r_info = 0;
(void) gelf_update_rel(data_rel, i, &rel);
}
#endif
mod = 1;
(void) elf_flagdata(data_tgt, ELF_C_SET, ELF_F_DIRTY);
@ -1750,11 +1575,8 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
* already been processed by an earlier link
* invocation.
*/
#ifndef illumos
#define SHN_SUNW_IGNORE SHN_ABS
#endif
if (rsym.st_shndx != SHN_SUNW_IGNORE) {
rsym.st_shndx = SHN_SUNW_IGNORE;
if (rsym.st_shndx != SHN_ABS) {
rsym.st_shndx = SHN_ABS;
(void) gelf_update_sym(data_sym, ndx, &rsym);
}
}
@ -1784,9 +1606,7 @@ int
dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
const char *file, int objc, char *const objv[])
{
#ifndef illumos
char tfile[PATH_MAX];
#endif
char drti[PATH_MAX];
dof_hdr_t *dof;
int fd, status, i, cur;
@ -1794,7 +1614,6 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
size_t len;
int eprobes = 0, ret = 0;
#ifndef illumos
if (access(file, R_OK) == 0) {
fprintf(stderr, "dtrace: target object (%s) already exists. "
"Please remove the target\ndtrace: object and rebuild all "
@ -1807,7 +1626,6 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
*/
return (0);
}
#endif
/*
* A NULL program indicates a special use in which we just link
@ -1870,23 +1688,11 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
if ((dof = dtrace_dof_create(dtp, pgp, dflags)) == NULL)
return (-1); /* errno is set for us */
#ifdef illumos
/*
* Create a temporary file and then unlink it if we're going to
* combine it with drti.o later. We can still refer to it in child
* processes as /dev/fd/<fd>.
*/
if ((fd = open64(file, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
return (dt_link_error(dtp, NULL, -1, NULL,
"failed to open %s: %s", file, strerror(errno)));
}
#else
snprintf(tfile, sizeof(tfile), "%s.XXXXXX", file);
if ((fd = mkostemp(tfile, O_CLOEXEC)) == -1)
return (dt_link_error(dtp, NULL, -1, NULL,
"failed to create temporary file %s: %s",
tfile, strerror(errno)));
#endif
/*
* If -xlinktype=DOF has been selected, just write out the DOF.
@ -1916,47 +1722,17 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
}
#ifdef illumos
if (!dtp->dt_lazyload)
(void) unlink(file);
#endif
if (dtp->dt_oflags & DTRACE_O_LP64)
status = dump_elf64(dtp, dof, fd);
else
status = dump_elf32(dtp, dof, fd);
#ifdef illumos
if (status != 0 || lseek(fd, 0, SEEK_SET) != 0) {
return (dt_link_error(dtp, NULL, -1, NULL,
"failed to write %s: %s", file, strerror(errno)));
}
#else
if (status != 0)
return (dt_link_error(dtp, NULL, -1, NULL,
"failed to write %s: %s", tfile,
strerror(dtrace_errno(dtp))));
#endif
if (!dtp->dt_lazyload) {
#ifdef illumos
const char *fmt = "%s -o %s -r -Blocal -Breduce /dev/fd/%d %s";
if (dtp->dt_oflags & DTRACE_O_LP64) {
(void) snprintf(drti, sizeof (drti),
"%s/64/drti.o", _dtrace_libdir);
} else {
(void) snprintf(drti, sizeof (drti),
"%s/drti.o", _dtrace_libdir);
}
len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, fd,
drti) + 1;
cmd = alloca(len);
(void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, fd, drti);
#else
const char *fmt = "%s -o %s -r %s %s";
dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
@ -1969,7 +1745,6 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
(void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, tfile,
drti);
#endif
if ((status = system(cmd)) == -1) {
ret = dt_link_error(dtp, NULL, fd, NULL,
"failed to run %s: %s", dtp->dt_ld_path,
@ -1992,7 +1767,6 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
}
(void) close(fd); /* release temporary file */
#ifdef __FreeBSD__
/*
* Now that we've linked drti.o, reduce the global __SUNW_dof
* symbol to a local symbol. This is needed to so that multiple
@ -2025,25 +1799,20 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
file, dtp->dt_objcopy_path, WEXITSTATUS(status));
goto done;
}
#endif
} else {
#ifdef __FreeBSD__
if (rename(tfile, file) != 0) {
ret = dt_link_error(dtp, NULL, fd, NULL,
"failed to rename %s to %s: %s", tfile, file,
strerror(errno));
goto done;
}
#endif
(void) close(fd);
}
done:
dtrace_dof_destroy(dtp, dof);
#ifdef __FreeBSD__
if (!dtp->dt_lazyload)
(void) unlink(tfile);
#endif
return (ret);
}