mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-15 10:17:20 +00:00
Extend ELF coredump to support more than 65535 segments
The ELF e_phnum field is only 16 bits wide. To support more than 65535 segments (program headers), Sun's "Linker and Libraries Guide" table 7-7 (or 12-7, depending on document version) prescribes a special first section header where sh_info represents the real number of program headers. Test code to follow, when it is ready. Reference: http://docs.oracle.com/cd/E18752_01/pdf/817-1984.pdf Reviewed by: emaste, markj Sponsored by: EMC / Isilon Storage Division Differential Revision: https://reviews.freebsd.org/D7255
This commit is contained in:
parent
9f3391243b
commit
c17b0bd2a6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=303099
@ -1323,6 +1323,8 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
|
||||
* Collect info about the core file header area.
|
||||
*/
|
||||
hdrsize = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * (1 + seginfo.count);
|
||||
if (seginfo.count + 1 >= PN_XNUM)
|
||||
hdrsize += sizeof(Elf_Shdr);
|
||||
__elfN(prepare_notes)(td, ¬elst, ¬esz);
|
||||
coresize = round_page(hdrsize + notesz) + seginfo.size;
|
||||
|
||||
@ -1618,10 +1620,10 @@ __elfN(puthdr)(struct thread *td, void *hdr, size_t hdrsize, int numsegs,
|
||||
{
|
||||
Elf_Ehdr *ehdr;
|
||||
Elf_Phdr *phdr;
|
||||
Elf_Shdr *shdr;
|
||||
struct phdr_closure phc;
|
||||
|
||||
ehdr = (Elf_Ehdr *)hdr;
|
||||
phdr = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr));
|
||||
|
||||
ehdr->e_ident[EI_MAG0] = ELFMAG0;
|
||||
ehdr->e_ident[EI_MAG1] = ELFMAG1;
|
||||
@ -1645,14 +1647,43 @@ __elfN(puthdr)(struct thread *td, void *hdr, size_t hdrsize, int numsegs,
|
||||
ehdr->e_flags = 0;
|
||||
ehdr->e_ehsize = sizeof(Elf_Ehdr);
|
||||
ehdr->e_phentsize = sizeof(Elf_Phdr);
|
||||
ehdr->e_phnum = numsegs + 1;
|
||||
ehdr->e_shentsize = sizeof(Elf_Shdr);
|
||||
ehdr->e_shnum = 0;
|
||||
ehdr->e_shstrndx = SHN_UNDEF;
|
||||
if (numsegs + 1 < PN_XNUM) {
|
||||
ehdr->e_phnum = numsegs + 1;
|
||||
ehdr->e_shnum = 0;
|
||||
} else {
|
||||
ehdr->e_phnum = PN_XNUM;
|
||||
ehdr->e_shnum = 1;
|
||||
|
||||
ehdr->e_shoff = ehdr->e_phoff +
|
||||
(numsegs + 1) * ehdr->e_phentsize;
|
||||
KASSERT(ehdr->e_shoff == hdrsize - sizeof(Elf_Shdr),
|
||||
("e_shoff: %zu, hdrsize - shdr: %zu",
|
||||
ehdr->e_shoff, hdrsize - sizeof(Elf_Shdr)));
|
||||
|
||||
shdr = (Elf_Shdr *)((char *)hdr + ehdr->e_shoff);
|
||||
memset(shdr, 0, sizeof(*shdr));
|
||||
/*
|
||||
* A special first section is used to hold large segment and
|
||||
* section counts. This was proposed by Sun Microsystems in
|
||||
* Solaris and has been adopted by Linux; the standard ELF
|
||||
* tools are already familiar with the technique.
|
||||
*
|
||||
* See table 7-7 of the Solaris "Linker and Libraries Guide"
|
||||
* (or 12-7 depending on the version of the document) for more
|
||||
* details.
|
||||
*/
|
||||
shdr->sh_type = SHT_NULL;
|
||||
shdr->sh_size = ehdr->e_shnum;
|
||||
shdr->sh_link = ehdr->e_shstrndx;
|
||||
shdr->sh_info = numsegs + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the program header entries.
|
||||
*/
|
||||
phdr = (Elf_Phdr *)((char *)hdr + ehdr->e_phoff);
|
||||
|
||||
/* The note segement. */
|
||||
phdr->p_type = PT_NOTE;
|
||||
|
Loading…
Reference in New Issue
Block a user