[DTrace-devel] [PATCH 3/4] Revert "usdt: remove relocations rather than changing their type to R_*_NONE"
Nick Alcock
nick.alcock at oracle.com
Fri Feb 9 18:56:58 UTC 2024
This reverts commit 2096fd774aa7459bb106337dc600acc25b31f3d6.
(Adjusted to keep the test in that commit.)
---
libdtrace/dt_link.c | 151 +++++++++++++++++---------------------------
1 file changed, 58 insertions(+), 93 deletions(-)
diff --git a/libdtrace/dt_link.c b/libdtrace/dt_link.c
index 59532370af5e..b2148a8b21d6 100644
--- a/libdtrace/dt_link.c
+++ b/libdtrace/dt_link.c
@@ -75,12 +75,11 @@ static const char DTRACE_SHSTRTAB64[] = "\0"
static const char DOFSTR[] = "__SUNW_dof";
static const char DOFLAZYSTR[] = "___SUNW_dof";
-typedef struct dt_link_set {
- struct dt_link_set *dlp_next; /* next set in linked list */
+typedef struct dt_link_pair {
+ struct dt_link_pair *dlp_next; /* next pair in linked list */
void *dlp_str; /* buffer for string table */
void *dlp_sym; /* buffer for symbol table */
- void *dlp_rel; /* buffer for relocations */
-} dt_link_set_t;
+} dt_link_pair_t;
typedef struct dof_elf32 {
uint32_t de_nrel; /* relocation count */
@@ -993,11 +992,11 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, GElf_Rela *rela, uint32_t *off)
/*PRINTFLIKE5*/
_dt_printflike_(5,6)
static int
-dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_set_t *bufs,
+dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_pair_t *bufs,
const char *format, ...)
{
va_list ap;
- dt_link_set_t *set;
+ dt_link_pair_t *pair;
va_start(ap, format);
dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
@@ -1009,12 +1008,11 @@ dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_set_t *bufs,
if (fd >= 0)
close(fd);
- while ((set = bufs) != NULL) {
- bufs = set->dlp_next;
- dt_free(dtp, set->dlp_str);
- dt_free(dtp, set->dlp_sym);
- dt_free(dtp, set->dlp_rel);
- dt_free(dtp, set);
+ while ((pair = bufs) != NULL) {
+ bufs = pair->dlp_next;
+ dt_free(dtp, pair->dlp_str);
+ dt_free(dtp, pair->dlp_sym);
+ dt_free(dtp, pair);
}
return dt_set_errno(dtp, EDT_COMPILER);
@@ -1034,7 +1032,6 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
Elf_Data *data_rel, *data_sym, *data_str, *data_tgt;
GElf_Shdr shdr_rel, shdr_sym, shdr_str, shdr_tgt;
GElf_Sym rsym, fsym, dsym;
- GElf_Rel rel;
GElf_Rela rela;
char *s, *p, *r;
char pname[DTRACE_PROVNAMELEN];
@@ -1043,7 +1040,7 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
uint32_t off, eclass, emachine1, emachine2;
size_t symsize, nsym, isym, istr, len;
key_t objkey;
- dt_link_set_t *set, *bufs = NULL;
+ dt_link_pair_t *pair, *bufs = NULL;
dt_strtab_t *strtab;
int flags = dtp->dt_link_no_mmap ? ELF_C_RDWR : ELF_C_RDWR_MMAP;
@@ -1114,8 +1111,6 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
scn_rel = NULL;
while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) {
- int nrel, j;
-
if (gelf_getshdr(scn_rel, &shdr_rel) == NULL)
goto err;
@@ -1182,23 +1177,19 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
* We take a first pass through all the relocations to
* populate our string table and count the number of extra
* symbols we'll require.
- *
- * We count the number of matching relocations so that we can
- * remove them from the relocation table once we are done with
- * them.
*/
strtab = dt_strtab_create(BUFSIZ);
nsym = 0;
isym = data_sym->d_size / symsize;
istr = data_str->d_size;
- nrel = 0;
- set = NULL;
for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
+
if (shdr_rel.sh_type == SHT_RELA) {
if (gelf_getrela(data_rel, i, &rela) == NULL)
continue;
} else {
+ GElf_Rel rel;
if (gelf_getrel(data_rel, i, &rel) == NULL)
continue;
rela.r_offset = rel.r_offset;
@@ -1217,8 +1208,6 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
if (strncmp(s, dt_prefix, sizeof(dt_prefix) - 1) != 0)
continue;
- nrel++;
-
if (dt_elf_symtab_lookup(data_sym, isym, rela.r_offset,
shdr_rel.sh_info, &fsym) != 0) {
dt_strtab_destroy(strtab);
@@ -1281,36 +1270,37 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
dt_strtab_destroy(strtab);
- if ((set = dt_zalloc(dtp, sizeof(*set))) == NULL)
+ if ((pair = dt_alloc(dtp, sizeof(*pair))) == NULL)
goto err;
- set->dlp_str = dt_alloc(dtp, data_str->d_size + len);
- if (set->dlp_str == NULL) {
- dt_free(dtp, set);
+ if ((pair->dlp_str = dt_alloc(dtp, data_str->d_size +
+ len)) == NULL) {
+ dt_free(dtp, pair);
goto err;
}
- set->dlp_sym = dt_alloc(dtp, data_sym->d_size +
- nsym * symsize);
- if (set->dlp_sym == NULL) {
- dt_free(dtp, set->dlp_str);
- dt_free(dtp, set);
+ if ((pair->dlp_sym = dt_alloc(dtp, data_sym->d_size +
+ nsym * symsize)) == NULL) {
+ dt_free(dtp, pair->dlp_str);
+ dt_free(dtp, pair);
goto err;
}
- set->dlp_next = bufs;
- bufs = set;
+ pair->dlp_next = bufs;
+ bufs = pair;
- memcpy(set->dlp_str, data_str->d_buf, data_str->d_size);
- data_str->d_buf = set->dlp_str;
+ memcpy(pair->dlp_str, data_str->d_buf,
+ data_str->d_size);
+ data_str->d_buf = pair->dlp_str;
data_str->d_size += len;
elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
shdr_str.sh_size += len;
gelf_update_shdr(scn_str, &shdr_str);
- memcpy(set->dlp_sym, data_sym->d_buf, data_sym->d_size);
- data_sym->d_buf = set->dlp_sym;
+ memcpy(pair->dlp_sym, data_sym->d_buf,
+ data_sym->d_size);
+ data_sym->d_buf = pair->dlp_sym;
data_sym->d_size += nsym * symsize;
elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
@@ -1326,12 +1316,13 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
* Now that the tables have been allocated, perform the
* modifications described above.
*/
- for (i = j = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize;
- i++) {
+ for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
+
if (shdr_rel.sh_type == SHT_RELA) {
if (gelf_getrela(data_rel, i, &rela) == NULL)
continue;
} else {
+ GElf_Rel rel;
if (gelf_getrel(data_rel, i, &rel) == NULL)
continue;
rela.r_offset = rel.r_offset;
@@ -1347,25 +1338,8 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
s = (char *)data_str->d_buf + rsym.st_name;
- if (strncmp(s, dt_prefix, sizeof(dt_prefix) - 1) != 0) {
- /*
- * If there was an earlier relocation that was
- * to be removed, we need to copy this one to
- * an earlier slot.
- */
- if (j < i) {
- mod = 1;
- elf_flagdata(data_rel, ELF_C_SET, ELF_F_DIRTY);
-
- if (shdr_rel.sh_type == SHT_RELA)
- gelf_update_rela(data_rel, j, &rela);
- else
- gelf_update_rel(data_rel, j, &rel);
- }
-
- j++;
+ if (strncmp(s, dt_prefix, sizeof(dt_prefix) - 1) != 0)
continue;
- }
s += sizeof(dt_prefix) - 1;
@@ -1467,40 +1441,32 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
*/
if (rsym.st_shndx != SHN_SUNW_IGNORE) {
mod = 1;
- elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
+ elf_flagdata(data_tgt, ELF_C_SET, ELF_F_DIRTY);
rsym.st_shndx = SHN_SUNW_IGNORE;
gelf_update_sym(data_sym, ndx, &rsym);
}
- }
- /*
- * If some relocations were removed, shrink the relocation
- * table.
- */
- if (nrel > 0) {
- size_t sz = data_rel->d_size -
- nrel * shdr_rel.sh_entsize;
+ /*
+ * This relocation is no longer needed. The linker on
+ * Linux doesn't know about SHN_SUNW_IGNORE, so we mark
+ * the relocation with type NONE. Failing to do so
+ * causes the linker to try to fill in an address on
+ * top of the NOPs we so carefully planted.
+ */
+ if (rela.r_info != GELF_R_INFO(ndx,0)) {
+ mod = 1;
+ elf_flagdata(data_tgt, ELF_C_SET, ELF_F_DIRTY);
+ if (shdr_rel.sh_type == SHT_RELA) {
+ rela.r_info = GELF_R_INFO(ndx, 0);
+ gelf_update_rela(data_rel, i, &rela);
+ } else {
+ GElf_Rel rel;
- /* If we do not have a link set yet, allocate one. */
- if (set == NULL) {
- set = dt_zalloc(dtp, sizeof(*set));
- if (set == NULL)
- goto err;
+ rel.r_offset = rela.r_offset;
+ rel.r_info = GELF_R_INFO(ndx, 0);
+ gelf_update_rel(data_rel, i, &rel);
+ }
}
-
- set->dlp_rel = dt_alloc(dtp, sz);
- if (set->dlp_rel == NULL)
- goto err;
-
- mod = 1;
- elf_flagdata(data_rel, ELF_C_SET, ELF_F_DIRTY);
-
- memcpy(set->dlp_rel, data_rel->d_buf, sz);
- data_rel->d_buf = set->dlp_rel;
- data_rel->d_size = sz;
-
- shdr_rel.sh_size = sz;
- gelf_update_shdr(scn_rel, &shdr_rel);
}
}
@@ -1510,12 +1476,11 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
elf_end(elf);
close(fd);
- while ((set = bufs) != NULL) {
- bufs = set->dlp_next;
- dt_free(dtp, set->dlp_str);
- dt_free(dtp, set->dlp_sym);
- dt_free(dtp, set->dlp_rel);
- dt_free(dtp, set);
+ while ((pair = bufs) != NULL) {
+ bufs = pair->dlp_next;
+ dt_free(dtp, pair->dlp_str);
+ dt_free(dtp, pair->dlp_sym);
+ dt_free(dtp, pair);
}
return 0;
--
2.43.0.272.gce700b77fd
More information about the DTrace-devel
mailing list