mirror of
https://github.com/openharmony/third_party_elfutils.git
synced 2026-07-19 19:43:34 -04:00
Fix read/write of existing file using mmap and different layout of the ELF
file.
This commit is contained in:
@@ -1,3 +1,16 @@
|
||||
2006-04-04 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* elf32_updatefile.c (updatemmap): Cleanups. Remove shdr_dest
|
||||
variable. Before writing sections, make a copy of the section
|
||||
header data if necessary. Don't write section header while
|
||||
writing the section constent, it might overwrite some sections.
|
||||
Restore the pointer afterwards.
|
||||
* elf32_updatenull.c (updatenull): If the offset of a section in a
|
||||
file changed make sure we read the section so that it'll be written
|
||||
out.
|
||||
|
||||
* elf_update.c: Remove debug message.
|
||||
|
||||
2005-12-07 Roland McGrath <roland@redhat.com>
|
||||
|
||||
* gelf_xlate.c [! ALLOW_UNALIGNED] (union unaligned): New type.
|
||||
|
||||
+70
-30
@@ -1,5 +1,5 @@
|
||||
/* Write changed data structures.
|
||||
Copyright (C) 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
|
||||
Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006 Red Hat, Inc.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <system.h>
|
||||
@@ -82,7 +83,6 @@ internal_function_def
|
||||
__elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Ehdr) *ehdr;
|
||||
xfct_t fctp;
|
||||
char *last_position;
|
||||
|
||||
/* We need the ELF header several times. */
|
||||
@@ -100,6 +100,7 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
|
||||
{
|
||||
/* Today there is only one version of the ELF header. */
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR];
|
||||
#else
|
||||
# undef fctp
|
||||
@@ -137,6 +138,7 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
|
||||
{
|
||||
/* Today there is only one version of the ELF header. */
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR];
|
||||
#else
|
||||
# undef fctp
|
||||
@@ -166,12 +168,11 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
|
||||
/* Write all the sections. Well, only those which are modified. */
|
||||
if (shnum > 0)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr_dest;
|
||||
Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
|
||||
Elf_Scn **scns = (Elf_Scn **) alloca (shnum * sizeof (Elf_Scn *));
|
||||
char *shdr_start = ((char *) elf->map_address + elf->start_offset
|
||||
+ ehdr->e_shoff);
|
||||
char *shdr_end = shdr_start + ehdr->e_shnum * ehdr->e_shentsize;
|
||||
char *const shdr_start = ((char *) elf->map_address + elf->start_offset
|
||||
+ ehdr->e_shoff);
|
||||
char *const shdr_end = shdr_start + ehdr->e_shnum * ehdr->e_shentsize;
|
||||
|
||||
#if EV_NUM != 2
|
||||
xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR];
|
||||
@@ -179,26 +180,43 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
|
||||
# undef shdr_fctp
|
||||
# define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
|
||||
#endif
|
||||
shdr_dest = (ElfW2(LIBELFBITS,Shdr) *)
|
||||
((char *) elf->map_address + elf->start_offset + ehdr->e_shoff);
|
||||
#define shdr_dest ((ElfW2(LIBELFBITS,Shdr) *) shdr_start)
|
||||
|
||||
/* Get all sections into the array and sort them. */
|
||||
sort_sections (scns, list);
|
||||
|
||||
/* We possibly have to copy the section header data because moving
|
||||
the sections might overwrite the data. */
|
||||
for (size_t cnt = 0; cnt < shnum; ++cnt)
|
||||
{
|
||||
Elf_Scn *scn = scns[cnt];
|
||||
|
||||
if ((scn->shdr_flags & ELF_F_MALLOCED) == 0
|
||||
&& scn->shdr.ELFW(e,LIBELFBITS) != &shdr_dest[scn->index])
|
||||
{
|
||||
assert ((char *) elf->map_address + elf->start_offset
|
||||
< (char *) scn->shdr.ELFW(e,LIBELFBITS));
|
||||
assert ((char *) scn->shdr.ELFW(e,LIBELFBITS)
|
||||
< (char *) elf->map_address + elf->maximum_size);
|
||||
|
||||
void *p = alloca (sizeof (ElfW2(LIBELFBITS,Shdr)));
|
||||
scn->shdr.ELFW(e,LIBELFBITS)
|
||||
= memcpy (p, scn->shdr.ELFW(e,LIBELFBITS),
|
||||
sizeof (ElfW2(LIBELFBITS,Shdr)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterate over all the section in the order in which they
|
||||
appear in the output file. */
|
||||
for (size_t cnt = 0; cnt < shnum; ++cnt)
|
||||
{
|
||||
Elf_Scn *scn = scns[cnt];
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr;
|
||||
char *scn_start;
|
||||
Elf_Data_List *dl;
|
||||
|
||||
shdr = scn->shdr.ELFW(e,LIBELFBITS);
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
|
||||
|
||||
scn_start = ((char *) elf->map_address
|
||||
+ elf->start_offset + shdr->sh_offset);
|
||||
dl = &scn->data_list;
|
||||
char *scn_start = ((char *) elf->map_address
|
||||
+ elf->start_offset + shdr->sh_offset);
|
||||
Elf_Data_List *dl = &scn->data_list;
|
||||
|
||||
if (shdr->sh_type != SHT_NOBITS && scn->data_list_rear != NULL)
|
||||
do
|
||||
@@ -236,10 +254,11 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
|
||||
if (unlikely (change_bo))
|
||||
{
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
|
||||
#else
|
||||
# undef fctp
|
||||
fctp = __elf_xfctstom[0][0][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
|
||||
# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
|
||||
#endif
|
||||
|
||||
/* Do the real work. */
|
||||
@@ -265,7 +284,23 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
|
||||
/* We have to trust the existing section header information. */
|
||||
last_position += shdr->sh_size;
|
||||
|
||||
/* Write the section header table entry if necessary. */
|
||||
scn->flags &= ~ELF_F_DIRTY;
|
||||
}
|
||||
|
||||
/* Fill the gap between last section and section header table if
|
||||
necessary. */
|
||||
if ((elf->flags & ELF_F_DIRTY)
|
||||
&& last_position < ((char *) elf->map_address + elf->start_offset
|
||||
+ ehdr->e_shoff))
|
||||
memset (last_position, __libelf_fill_byte,
|
||||
(char *) elf->map_address + elf->start_offset + ehdr->e_shoff
|
||||
- last_position);
|
||||
|
||||
/* Write the section header table entry if necessary. */
|
||||
for (size_t cnt = 0; cnt < shnum; ++cnt)
|
||||
{
|
||||
Elf_Scn *scn = scns[cnt];
|
||||
|
||||
if ((scn->shdr_flags | elf->flags) & ELF_F_DIRTY)
|
||||
{
|
||||
if (unlikely (change_bo))
|
||||
@@ -277,25 +312,28 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
|
||||
scn->shdr.ELFW(e,LIBELFBITS),
|
||||
sizeof (ElfW2(LIBELFBITS,Shdr)));
|
||||
|
||||
/* If we previously made a copy of the section header
|
||||
entry we now have to adjust the pointer again so
|
||||
point to new place in the mapping. */
|
||||
if ((scn->shdr_flags & ELF_F_MALLOCED) == 0)
|
||||
scn->shdr.ELFW(e,LIBELFBITS) = &shdr_dest[scn->index];
|
||||
|
||||
scn->shdr_flags &= ~ELF_F_DIRTY;
|
||||
}
|
||||
|
||||
scn->flags &= ~ELF_F_DIRTY;
|
||||
}
|
||||
|
||||
/* Fill the gap between last section and section header table if
|
||||
necessary. */
|
||||
if ((elf->flags & ELF_F_DIRTY)
|
||||
&& last_position < ((char *) elf->map_address + elf->start_offset
|
||||
+ ehdr->e_shoff))
|
||||
memset (last_position, __libelf_fill_byte,
|
||||
(char *) elf->map_address + elf->start_offset + ehdr->e_shoff
|
||||
- last_position);
|
||||
}
|
||||
|
||||
/* That was the last part. Clear the overall flag. */
|
||||
elf->flags &= ~ELF_F_DIRTY;
|
||||
|
||||
/* Make sure the content hits the disk. */
|
||||
char *msync_start = ((char *) elf->map_address
|
||||
+ elf->start_offset / sysconf (_SC_PAGESIZE));
|
||||
char *msync_end = ((char *) elf->map_address
|
||||
+ elf->start_offset + ehdr->e_shoff
|
||||
* ehdr->e_shentsize * shnum);
|
||||
(void) msync (msync_start, msync_end - msync_start, MS_SYNC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -349,7 +387,6 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
|
||||
{
|
||||
char fillbuf[FILLBUFSIZE];
|
||||
size_t filled = 0;
|
||||
xfct_t fctp;
|
||||
|
||||
/* We need the ELF header several times. */
|
||||
ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
|
||||
@@ -369,6 +406,7 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
|
||||
{
|
||||
/* Today there is only one version of the ELF header. */
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR];
|
||||
#else
|
||||
# undef fctp
|
||||
@@ -419,6 +457,7 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
|
||||
{
|
||||
/* Today there is only one version of the ELF header. */
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR];
|
||||
#else
|
||||
# undef fctp
|
||||
@@ -525,10 +564,11 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
|
||||
if (unlikely (change_bo))
|
||||
{
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
|
||||
#else
|
||||
# undef fctp
|
||||
fctp = __elf_xfctstom[0][0][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
|
||||
# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
|
||||
#endif
|
||||
|
||||
buf = tmpbuf;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Update data structures for changes.
|
||||
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
|
||||
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@@ -319,8 +319,18 @@ __elfw2(LIBELFBITS,updatenull) (Elf *elf, int *change_bop, size_t shnum)
|
||||
scn->shdr_flags);
|
||||
|
||||
size = (size + sh_align - 1) & ~(sh_align - 1);
|
||||
int offset_changed = 0;
|
||||
update_if_changed (shdr->sh_offset, (GElf_Word) size,
|
||||
changed);
|
||||
offset_changed);
|
||||
changed |= offset_changed;
|
||||
|
||||
if (offset_changed && scn->data_list_rear == NULL)
|
||||
{
|
||||
/* The position of the section in the file
|
||||
changed. Create the section data list. */
|
||||
if (INTUSE(elf_getdata) (scn, NULL) == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* See whether the section size is correct. */
|
||||
update_if_changed (shdr->sh_size, (GElf_Word) offset,
|
||||
|
||||
+2
-10
@@ -1,5 +1,5 @@
|
||||
/* Update data structures for changes and write them out.
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006 Red Hat, Inc.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@@ -181,15 +181,7 @@ elf_update (elf, cmd)
|
||||
size = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (elf->parent != NULL)
|
||||
{
|
||||
extern int puts (const char *);
|
||||
puts ("this is an archive member");
|
||||
}
|
||||
|
||||
size = write_file (elf, size, change_bo, shnum);
|
||||
}
|
||||
size = write_file (elf, size, change_bo, shnum);
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
Reference in New Issue
Block a user