Skip to content

Commit

Permalink
Merge branch 'cross_prelink_staging' into master_staging
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Hatle <[email protected]>
  • Loading branch information
Mark Hatle committed Aug 18, 2016
2 parents e7d3832 + ef20628 commit 5d21c44
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
9 changes: 9 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
2016-08-17 Mark Hatle <[email protected]>
* README: Update to include a few known issues

2016-08-17 Mark Hatle <[email protected]>
* src/rtld/dl-open.c: Change to work with older compilers

2016-06-03 Dave Lerner <[email protected]>
* src/exec.c: New check_reorder_needed, section_reorder_fix functions

2016-03-22 Mark Hatle <[email protected]>
* src/gather.c, src/get.c: Fix LD_PRELOAD
* Merge with cross_prelink
Expand Down
18 changes: 18 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,21 @@ Cc: [email protected]
Subject: [prelink-cross] ....


Known Issues
------------

The --preload option does not always work. The preload1 test currently fails.

quick2 test will fail if you do not have static libc installed.

IFUNC on glibc. glibc appears to have a bug related to specific IFUNC
ordering. build_local_scope in glibc is processing depth first instead of
breadth-first processing as it should be. The prelink-rtld version works
around this issue. (Prelink-rtld is only available in the cross compile
version.) See:

https://bugzilla.yoctoproject.org/show_bug.cgi?id=9131

ARM & PPC: both are currently failing the reloc8 and reloc9 test
Further investigation is in progress on these items. Until an explanation
is found, you should hold off using this for ARM and PPC.
92 changes: 92 additions & 0 deletions src/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,91 @@ update_dynamic_tags (DSO *dso, GElf_Shdr *shdr, GElf_Shdr *old_shdr,
return 0;
}

static int
check_reorder_needed(DSO *dso, struct section_move *moves, int fixed_shstrndx,
int fixed_undo, int fixed_strtab, int fixed_symtab)
{
const char *shstrtab_str =
strptr (dso, fixed_shstrndx, dso->shdr[fixed_shstrndx].sh_name);
const char *prelink_undo_str =
strptr (dso, fixed_shstrndx, dso->shdr[fixed_undo].sh_name);
const char *strtab_str =
strptr (dso, fixed_shstrndx, dso->shdr[fixed_strtab].sh_name);
const char *symtab_str =
strptr (dso, fixed_shstrndx, dso->shdr[fixed_symtab].sh_name);

if (!shstrtab_str || !prelink_undo_str || !strtab_str || !symtab_str
|| strcmp (shstrtab_str, ".shstrtab")
|| strcmp(prelink_undo_str, ".gnu.prelink_undo")
|| strcmp(strtab_str, ".strtab")
|| strcmp(symtab_str, ".symtab")
|| (moves->old_to_new[fixed_shstrndx] == fixed_shstrndx)
|| (dso->shdr[fixed_shstrndx].sh_offset < dso->shdr[fixed_strtab].sh_offset)
|| (dso->shdr[fixed_shstrndx].sh_offset < dso->shdr[fixed_symtab].sh_offset))
return 0;

return 1;
}

/*
* Some linkers create a binary which has a section header table that is
* not in section header offset order. However, as noted in check_dso(),
* several routines in prelink and in libelf-0.7.0 too rely on sh_offsets
* monotonically increasing, and if that fails then prelink quits. But
* the check is only on dso's, not binaries. For binaries, fdopen_dso()
* reorders the section headers to section header offset order prior to
* work on the section data, so that the new prelinked binary is written
* in section order.
* However, on subsequent prelinks of a prelinked binary, the
* prelink_exec() works on the undone section, not the fdopen_dso()
* reordered sections, and may construct a section header table with
* section orders different than the first prelink of the binary.
* The function below tests for that case and resets the section header
* order to the offset order by enforcing the binutils linker change:
* 'The net effect is .shstrab section is now placed after .symtab and
* .strtab sections'. See binutils-gdb.git commit 3e19fb8f990e4c.
*/
static void
section_reorder_fix(DSO *dso, GElf_Shdr *shdr, struct section_move *move,
int *undo)
{
int i;
int fixed_shstrndx = dso->ehdr.e_shstrndx;
int fixed_undo = fixed_shstrndx - 1;
int fixed_strtab = fixed_shstrndx- 2;
int fixed_symtab = fixed_shstrndx - 3;
int section_reorder_cnt = 4;
GElf_Shdr undone_shdr[dso->ehdr.e_shnum];

if (!check_reorder_needed(dso, move,
fixed_shstrndx, fixed_undo, fixed_strtab, fixed_symtab))
return;

/* get a copy of the undo section's shdr ordering */
for (i = 0 ; i < dso->ehdr.e_shnum; ++i)
undone_shdr[i] = shdr[i];

/* copy the undo section's shdr to the corrected index */
for (i = 0 ; i < section_reorder_cnt; ++i)
{
int ndx = fixed_shstrndx - i;
if (ndx != fixed_undo)
{
shdr[ndx] = undone_shdr[move->old_to_new[ndx]];
move->old_to_new[ndx] = ndx;
move->new_to_old[ndx] = ndx;
}
else
{
shdr[fixed_undo] = undone_shdr[*undo];
/* the moves are specially flagged for the undo secton */
move->old_to_new[fixed_undo] = -1;
move->new_to_old[fixed_undo] = -1;
}
}
*undo = fixed_undo;
}

int
prelink_exec (struct prelink_info *info)
{
Expand All @@ -93,6 +178,7 @@ prelink_exec (struct prelink_info *info)
Elf32_Lib *liblist = NULL;
struct readonly_adjust adjust;
struct section_move *move = NULL;
int undo_sections_done = 0;

if (prelink_build_conflicts (info))
return 1;
Expand Down Expand Up @@ -140,7 +226,9 @@ prelink_exec (struct prelink_info *info)
goto error_out;
}
memcpy (dso->undo.d_buf, data->d_buf, data->d_size);

ehdr.e_shstrndx = dso->ehdr.e_shstrndx;
undo_sections_done = 1;
}
undo = 0;

Expand Down Expand Up @@ -438,6 +526,10 @@ prelink_exec (struct prelink_info *info)
ehdr.e_shnum = dso->ehdr.e_shnum;
dso->ehdr = ehdr;
memcpy (dso->phdr, phdr, ehdr.e_phnum * sizeof (GElf_Phdr));

if (undo_sections_done)
section_reorder_fix(dso, shdr, move, &undo);

if (reopen_dso (dso, move, NULL))
goto error_out;

Expand Down

0 comments on commit 5d21c44

Please sign in to comment.